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:
| Hive | Long name | Typical use |
|---|---|---|
HKCU | HKEY_CURRENT_USER | Settings for the signed-in user |
HKLM | HKEY_LOCAL_MACHINE | Machine-wide application and Windows configuration |
HKU | HKEY_USERS | Settings organized by user security identifier (SID) |
HKCC | HKEY_CURRENT_CONFIG | The 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 type | Represents |
|---|---|
winreg_root | The Registry realm |
winreg_hive | A live hive such as HKCU |
winreg_key | A key or subkey |
winreg_property | A 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:
| Target | Example location | Usual approach |
|---|---|---|
| Per-user application preferences | HKCU/Software/Vendor/Application | Track specific values; writable profiles are often appropriate |
| Per-user startup commands | HKCU/Software/Microsoft/Windows/CurrentVersion/Run | Track only the named programs you manage |
| Per-user file associations | HKCU/Software/Classes | Track the relevant class or extension branch |
| Machine-wide application settings | HKLM/SOFTWARE/Vendor/Application | Track 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
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 type | Data represented |
|---|---|
REG_SZ | Text |
REG_EXPAND_SZ | Text that may contain expandable environment variables |
REG_DWORD | 32-bit integer |
REG_QWORD | 64-bit integer |
REG_MULTI_SZ | List of text strings |
REG_BINARY | Binary 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:
- Pinman extracts the schema-tracked keys directly. These explicit selections are not restricted by the broad-extraction allowlist or blacklist.
- For each Registry hive present in the schema, Pinman extracts only the top-level
branches named by
allowed_subtrees. - 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:
| Hive | Broadly extracted subtrees |
|---|---|
HKCU | Software, Control Panel, Environment |
HKLM | SOFTWARE, 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:
| Section | Purpose |
|---|---|
allowed_subtrees | The top-level hive branches eligible for broad extraction |
key_patterns | Registry key paths or names excluded from broad extraction |
value_patterns | Value 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:
- Create a capture with Scope: Discover untracked and Back up files enabled.
- Pinman freezes the discovered Registry state and retains the bounded
.regextracts. - Later, use Scan for untracked in the Head while comparing against that frozen capture.
- 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.


