Skip to content

nkdAgility/machine-state

Repository files navigation

machine-state

PowerShell-first machine rebuild and synchronization for named workstations.

YAML says what.
PowerShell says how.
machine-state.ps1 decides when.
working/ shows what happened.

Purpose

Rebuild, update, export, and synchronize workstation state in a deterministic way. Given the same input YAML, the output is always the same.

Supported Machines

Name Platform Notes
NKDA-BEHEMOTH Windows x64 Intel i9, NVIDIA GPU
NKDA-ROCINANTE Windows ARM64 Snapdragon Surface, 64 GB RAM

Fresh Machine Bootstrap

On a brand-new Windows machine — nothing installed, repo not cloned — open an elevated PowerShell prompt and run:

irm https://raw.githubusercontent.com/nkdAgility/machine-state/main/bootstrap.ps1 | iex

This single command will:

  1. Ensure winget is available:
    • Windows 11 / Windows Server 2025 — ships pre-installed; verified on PATH.
    • Windows Server 2019 / 2022 — automatically installs VCLibs, Microsoft.UI.Xaml, and the winget msixbundle, then fixes PATH.
    • Windows 10 client — prompts to install App Installer from the Microsoft Store if winget is absent.
  2. Install PowerShell 7 via winget
  3. Install Git via winget
  4. Clone this repo to %USERPROFILE%\source\repos\machine-state
  5. Install powershell-yaml under pwsh 7
  6. Hand off to machine-state.ps1 apply under PowerShell 7

If the repo is already cloned it pulls the latest instead of re-cloning. Safe to re-run at any time.

Tip — WhatIf: append -WhatIf to the final pwsh call inside bootstrap.ps1 if you want to preview what would be installed without making any changes.


How to Run (repo already cloned)

./machine-state.ps1 sync           # Capture current state, then apply desired state
./machine-state.ps1 capture        # Record current machine state only
./machine-state.ps1 apply          # Install everything from stored config
./machine-state.ps1 status         # Show resolved machine, files, scripts, and paths
./machine-state.ps1 validate       # Check state files are valid without installing

-MachineName is optional. If omitted the machine is resolved from $env:COMPUTERNAME.

Two Distinct Concerns

Primary State

Primary state is everything the machine needs installed. It lives in YAML under state/ and is managed by the engine pipeline (merge → build → execute).

Concern Where it lives
Winget packages (base) state/win/windows-base.yaml
Winget packages (common/personal) state/win/windows-common.yaml, state/machines/<Name>.yaml
Node / npm globals state/win/windows-common.yaml
Python / uv tools state/win/windows-common.yaml
.NET global tools state/common-base.yaml, state/common-personal.yaml
PowerShell modules state/common-base.yaml, state/common-personal.yaml
Git repositories state/common-base.yaml, state/common-personal.yaml
Windows OS setup state/win/windows-base.yaml (setup.windows)
Git global config state/common-base.yaml (setup.git)

The engine merges these, deduplicates by id, sorts deterministically, and writes a combined manifest to working/<MachineName>/ before executing.

App Configuration

App configuration is everything needed to configure an already-installed application — dotfiles, registry settings, profile entries, backup/restore of app data.

Each app has scripts under scripts/apps/<Publisher.AppName>/:

Script Stage Purpose
apply.ps1 Execute Configure or install the app
capture.ps1 Capture Export app state back to state/config/
build.ps1 Build Prepare artifacts (rarely needed)

Only create the scripts you need — none are required. For apps not available in winget, apply.ps1 checks the Windows registry and downloads/installs the app directly if missing.

App Scripts Config
Git apply.ps1 (global git config — no files)
Oh My Posh apply.ps1, capture.ps1 state/config/JanDeDobbeleer.OhMyPosh/
Stream Deck apply.ps1, capture.ps1 state/config/Elgato.StreamDeck/
VS Code apply.ps1 (settings synced via VS Code)
OBS Studio apply.ps1, capture.ps1 state/config/OBSProject.OBSStudio/
NVIDIA AR SDK apply.ps1 (ad-hoc installer — not in winget)
GitHub Copilot apply.ps1 (ad-hoc installer — not in winget)

Stages

Stage What it does
export Read current machine state into working/<MachineName>/export/
merge Combine all referenced YAML into working/<MachineName>/machine-state.yaml
build Generate tool-specific manifests in working/<MachineName>/build/
execute Apply desired state — install packages, configure apps
sync Run all four stages in order
capture Export then update stored YAML with any new packages found
status Show resolved machine, config paths, and scripts
validate Check YAML shape and references without installing

Repository Layout

state/
  common-base.yaml      ← every machine: git config, engine PS modules (powershell-yaml, pester)
  common-personal.yaml  ← personal machines: dotnet tools, personal PS modules, git repos
  machines/             ← one file per named workstation; unknown machines use client-default.yaml
  win/
    windows-base.yaml   ← every Windows machine: ~17 universal dev tools + OS setup
    windows-common.yaml ← personal Windows: OBS, StreamDeck, Elgato, VS Enterprise, etc.
    windows-x64.yaml    ← x64-specific packages
    windows-arm64.yaml  ← ARM64-specific packages
  config/               ← app config files committed to the repo, one folder per Publisher.AppName

scripts/
  State-Engine.ps1
  Setup-Engine.ps1
  Resolver-Common.ps1
  systems/
    WindowsSetup/Resolve.ps1    ← Windows OS configuration
    Winget/Resolve.ps1          ← winget + msstore packages
    DotNet/Resolve.ps1          ← dotnet global tools
    PSModule/Resolve.ps1        ← PowerShell modules
    Node/Resolve.ps1            ← npm global packages
    Uv/Resolve.ps1              ← uv tools
    GitRepos/Resolve.ps1        ← git repo clone/pull
    GitReposCleanup/Resolve.ps1 ← git branch cleanup
  apps/
    Git.Git/apply.ps1
    JanDeDobbeleer.OhMyPosh/apply.ps1
    JanDeDobbeleer.OhMyPosh/capture.ps1
    Elgato.StreamDeck/apply.ps1
    Elgato.StreamDeck/capture.ps1
    Microsoft.VisualStudioCode/apply.ps1
    OBSProject.OBSStudio/apply.ps1
    OBSProject.OBSStudio/capture.ps1
    Nvidia.ArSDK/apply.ps1
    GitHub.GitHubCopilot/apply.ps1

working/              ← generated outputs (gitignored)

Working Folder

All generated files go under working/<MachineName>/:

export/                     ← observed current state
  winget.export.json
  node.npm.export.json
  uv.tools.export.json
  git.export.json
  windows.setup.json

machine-state.yaml          ← merged desired state (YAML)
machine-state.json          ← merged desired state (JSON)

build/                      ← tool-specific install manifests
  winget.import.json
  winget.upgrades.json
  node.npm.import.json
  uv.tools.import.json
  git.ops.json

logs/                       ← execution logs

These are outputs. state/ is the source of truth.

Determinism

  • Package entries are deduplicated by id
  • Package lists are sorted by id
  • Output files are written to predictable paths
  • The same input YAML always produces the same generated output

LLM Boundary

LLMs may help maintain this repository. No LLM is required to run it. Execution depends only on PowerShell 7+, Winget, and powershell-yaml. See CLAUDE.md for contributor guidance.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors