Technical guide

Windows Registry

The Windows Registry is a hierarchical database used by Windows and many applications to store configuration. Pinman can track selected Registry keys and values beside files and other system settings, so they can be compared in captures and used by profiles.

This guide explains the Registry model, how Pinman represents it, and how to choose a useful tracking boundary. It assumes you already know the basics of a Pinman schema.

Registry structure#

The Registry is organized as a tree. For example, an installed app, Example App might have stored the following:

HKEY_CURRENT_USER                         hive
└── Software                             key
    └── Example Company                  key
        └── Example App                  key
            ├── Theme = "Dark"            named value (REG_SZ)
            ├── CheckForUpdates = 1      named value (REG_DWORD)
            └── (Default) = "Example"     unnamed value

A hive is a top-level Registry tree. A key is a container, comparable to a directory. A key can contain subkeys and values. Each value has a name, a Registry data type, and data. Despite the name, a Registry value is a complete named entry—not just the data stored in it.

Windows also permits one unnamed value per key. Registry tools usually display it as (Default). In a Pinman schema, that value has an empty selector.

Live hives#

Pinman accepts the common abbreviated hive names in winreg: locations:

HiveLong nameTypical use
HKCUHKEY_CURRENT_USERSettings for the signed-in user
HKLMHKEY_LOCAL_MACHINEMachine-wide application and Windows configuration
HKUHKEY_USERSSettings organized by user security identifier (SID)
HKCCHKEY_CURRENT_CONFIGThe current hardware profile

HKEY_CLASSES_ROOT (HKCR) is a merged Windows view rather than an independent store. Pinman does not use it as a live hive. Track the underlying entry in HKCU/Software/Classes or HKLM/Software/Classes instead.

How Pinman maps the Registry#

Registry items use the winreg: realm and the same parent-child shape as the live Registry:

Pinman item typeRepresents
winreg_rootThe Registry realm
winreg_hiveA live hive such as HKCU
winreg_keyA key or subkey
winreg_propertyA named or unnamed value inside a key

Locations use forward slashes even though Windows tools commonly display Registry paths with backslashes:

winreg:/HKCU/Software/Example Company/Example App

Hive and key containers are structural. The leaf winreg_property items are the values whose data and Registry type Pinman records and compares. Names are matched without regard to case, as they are in Windows.

When a schema names a complete winreg: location, Pinman creates the hive and any missing intermediate key containers in its compiled tree. Those containers make the hierarchy readable; they do not broaden what is tracked.

Common tracking targets include:

TargetExample locationUsual approach
Per-user application preferencesHKCU/Software/Vendor/ApplicationTrack specific values; writable profiles are often appropriate
Per-user startup commandsHKCU/Software/Microsoft/Windows/CurrentVersion/RunTrack only the named programs you manage
Per-user file associationsHKCU/Software/ClassesTrack the relevant class or extension branch
Machine-wide application settingsHKLM/SOFTWARE/Vendor/ApplicationTrack selectively; expect permission limits

These locations are examples of structure, not blanket recommendations to track an entire branch.

Declare keys and values#

This example tracks two ordinary per-user application settings:

items:
  - location: "winreg:/HKCU/Software/Example Company/Example App"
    itemtype: winreg_key
    label: Example App settings
    items:
      - selector: Theme
        label: Theme
      - selector: CheckForUpdates
        label: Check for updates

Under a winreg_key, a child without an explicit itemtype defaults to a winreg_property. You can spell it out when that makes a shared schema easier to read:

      - selector: Theme
        itemtype: winreg_property

You may declare a value even when it is currently absent. Absence is meaningful Registry state: a program may use a built-in default until a value is created, or enable a feature only while a value exists. After the value is declared, Pinman can distinguish present, absent, and unavailable state. An access failure is not reported as a deletion.

Track a controlled group of values#

If an application owns a key and the useful set of values is not fixed, use matching rules deliberately:

items:
  - location: "winreg:/HKCU/Software/Example Company/Example App"
    itemtype: winreg_key
    schema_props:
      include_local: ["Display*"]
      exclude_local: ["*Cache*"]

include_local and exclude_local apply to direct children of this key. include_match and exclude_match are inherited by descendant keys. Prefer explicit values when the setting names are stable; patterns are best when the application owns a well-defined family of values.

Example: Start Pinman at login#

Windows starts per-user programs from values under this key:

HKCU/Software/Microsoft/Windows/CurrentVersion/Run

Pinman's Start at Login setting is represented by the Pinman value. When the setting is on, the value is present and contains the launch command. When it is off, the value is absent. A schema can track that one value without tracking any other startup programs:

items:
  - location: "winreg:/HKCU"
    itemtype: winreg_hive
    items:
      - location: "Software/Microsoft/Windows/CurrentVersion/Run"
        itemtype: winreg_key
        label: User Startup Programs
        items:
          - selector: Pinman
            label: Start Pinman at Login

Start Pinman at Login as one tracked value beneath the Run key

The Track Registry state tutorial walks through declaring the value, capturing its present and absent states, and comparing the result.

Registry value types#

Pinman reads and preserves these native Registry types:

Registry typeData represented
REG_SZText
REG_EXPAND_SZText that may contain expandable environment variables
REG_DWORD32-bit integer
REG_QWORD64-bit integer
REG_MULTI_SZList of text strings
REG_BINARYBinary value data

Type is part of the value's state. The text "1" stored as REG_SZ is not the same Registry value as the number 1 stored as REG_DWORD. When Pinman updates an existing value through a profile, it retains the value's known native type. A newly created value without recorded type information defaults to REG_SZ.

Read and compare Registry state#

Refresh or capture a project after the relevant software has changed. Pinman reads only the Registry scope selected by the schema, then shows tracked values alongside other configuration in Explore and captures. Comparisons can show:

  • a value's data changing;
  • a value being created or removed;
  • a tracked key appearing or disappearing; or
  • a value that could not be read because the key was unavailable.

For a direct, read-only inspection outside a project, use:

pinman winreg show "HKCU/Software/Example Company/Example App"

Add --recursive to include subkeys, or -o json for structured output. This command is useful for confirming a path and value names before adding them to a schema.

Broad extraction and discovery captures#

A tracked-only capture extracts the Registry keys selected by the schema. A capture with Scope: Discover untracked—also called Discovery (tracked_only: false)—adds a broader Registry extraction so Pinman can also find untracked keys and values.

This is sometimes described as extracting the “entire” Registry, but it is deliberately bounded:

  1. Pinman extracts the schema-tracked keys directly. These explicit selections are not restricted by the broad-extraction allowlist or blacklist.
  2. For each Registry hive present in the schema, Pinman extracts only the top-level branches named by allowed_subtrees.
  3. Key and value patterns from the Registry blacklist remove known churn and noise from those broad branches.

The Windows baseline currently allows these broad branches:

HiveBroadly extracted subtrees
HKCUSoftware, Control Panel, Environment
HKLMSOFTWARE, SYSTEM, HARDWARE

Other hives and branches can still be read when the schema explicitly tracks them; they are simply outside the default broad discovery sweep. This keeps a discovery capture useful without turning it into an unbounded copy of every Registry branch.

winreg_blacklist.jsonc#

The broad-extraction boundary and noise filters live together in winreg_blacklist.jsonc. Pinman ships a Windows baseline at data/platform/windows/reference/winreg_blacklist.jsonc. A project can replace that baseline for itself by placing a file with the same name in its reference directory; the project file takes precedence rather than being merged with the packaged file. The resolved file is project-wide: every broad Registry extraction in that project uses the same allowlist and blacklist.

The file has three important parts:

SectionPurpose
allowed_subtreesThe top-level hive branches eligible for broad extraction
key_patternsRegistry key paths or names excluded from broad extraction
value_patternsValue names excluded from broad extraction

The distinction is meaningful configuration versus churn. A theme choice, feature toggle, application path, file association, or other deliberate preference may be worth tracking. Most-recently-used lists, caches, telemetry, session identifiers, timestamps, usage counters, update bookkeeping, and similar autonomous activity usually are not. Without filtering, two captures taken with no intentional configuration change could still contain thousands of irrelevant differences.

Blacklist entries include comments that explain why each pattern exists. Treat a project override as configuration, not as a harmless formatting file: removing a pattern can greatly increase capture size and noise, while an overly broad pattern can hide useful untracked evidence. It cannot hide a key the schema explicitly tracks.

Backing up the Registry#

Every capture performs the Registry extraction it needs in order to scan; Back up files decides whether those extracted bytes are retained. When backup is enabled, Pinman copies the generated .reg files—including the tracked-key overlay and any broad subtree extracts—into the capture's winreg directory. A capture without file backup records its scan results but does not retain those extract files for later inspection.

This makes a Savepoint+ especially useful as a reference:

  1. Create a capture with Scope: Discover untracked and Back up files enabled.
  2. Pinman freezes the discovered Registry state and retains the bounded .reg extracts.
  3. Later, use Scan for untracked in the Head while comparing against that frozen capture.
  4. Pinman reads the selected live Registry level and can compare it with the stored Registry evidence from the reference capture.

That workflow helps identify keys and values that deserve a permanent place in the schema. It is also useful during troubleshooting: the reference preserves what the bounded Registry looked like before a software installation, settings change, or system problem. The frozen capture is never refreshed from the live machine; its comparisons come from the Registry files retained at capture time.

Writes, permissions, and safe scope#

Reading a value does not guarantee that the current account can change it. Per-user application configuration under HKCU/Software is usually the safest writable scope. Machine-wide keys under HKLM commonly require elevated permissions and are often better treated as read-only evidence.

Profiles can create, update, and remove supported tracked values. Preview a profile before applying it, especially when it has more than one target: a runtime failure can occur after an earlier target has already changed. Pinman blocks writes to protected Windows security, boot, sign-in, and policy paths.

Not every Windows setting should be addressed as a raw Registry value. If Windows exposes a supported system API for a setting—such as master audio or display configuration—use the Windows Runtime realm. It gives Pinman the setting's Windows-level meaning and safer read/write behavior.

Practical boundaries#

  • Track the smallest key and value set that expresses the configuration you care about.
  • Prefer per-user application settings when you intend to apply profiles.
  • Treat credentials, tokens, license material, and other secrets as out of scope.
  • Do not assume every value under an application key is stable configuration; many are caches, counters, timestamps, and recent-use history.
  • Close or pause an application before applying its Registry settings if the application may overwrite them while it is running.