This commit is contained in:
2026-07-29 04:01:25 +09:00
parent 601c94a5d8
commit 3f35a54e0a
18 changed files with 695 additions and 2 deletions
+2 -2
View File
@@ -23,10 +23,10 @@
!/images/ !/images/
!/secrets/ !/secrets/
!/windows/
!/hosts/ !/hosts/
!/libs/ !/libs/
!/modules/ !/modules/
!/tests/ !/tests/
+383
View File
@@ -0,0 +1,383 @@
# Windows dotfiles
This directory contains the Windows-specific configuration for this dotfiles
repository.
The design has four layers:
1. **Native package declarations**
- Scoop uses `Scoopfile.json`.
- WinGet / Microsoft Store packages use DSC `Microsoft.WinGet/Package`.
2. **Windows desired state**
- Windows settings use DSC resources grouped by settings domain.
3. **Application-owned configuration**
- Each application that needs files or CLI-based configuration has its own
directory and its own small `apply.ps1`.
4. **One root entry point**
- `update.ps1` only invokes the native package/configuration systems and the
application-specific apply scripts.
The root script intentionally contains no application-specific paths, registry
logic, wallpaper loop, or VS Code extension list.
## Layout
```text
windows/
├── README.md
├── update.ps1
├── Scoopfile.json
├── configuration.dsc.yaml
│
├── packages/
│ └── winget.dsc.yaml
│
├── system/
│ ├── taskbar.dsc.yaml
│ ├── explorer.dsc.yaml
│ ├── ime.dsc.yaml
│ └── wallpaper/
│ ├── apply.ps1
│ └── wallpaper.theme
│
└── applications/
├── chatgpt/
│ └── apply.ps1
├── git/
│ ├── apply.ps1
│ └── gitconfig
│
└── vscode/
├── apply.ps1
├── settings.json
├── argv.json
└── extensions.txt
```
## Fresh Windows installation
Open a normal, non-elevated PowerShell window.
### 1. Allow local scripts
```powershell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```
### 2. Install Scoop and bootstrap Git
```powershell
Invoke-RestMethod https://get.scoop.sh | Invoke-Expression
scoop install git
```
### 3. Clone dotfiles
```powershell
git clone https://github.com/moons-14/dotfiles.git "$HOME\dotfiles"
Set-Location "$HOME\dotfiles\windows"
```
### 4. Install Microsoft DSC v3
```powershell
winget install --id 9NVTPZWRC6KQ --source msstore
```
If `dsc` is not available in the current shell immediately after installation,
open a new PowerShell window and return to:
```powershell
Set-Location "$HOME\dotfiles\windows"
```
### 5. Apply everything
```powershell
.\update.ps1
```
## Normal workflow
```powershell
Set-Location "$HOME\dotfiles\windows"
git pull
.\update.ps1
```
`update.ps1` stays intentionally small:
```powershell
scoop update
scoop import .\Scoopfile.json
scoop update *
dsc config set --file .\configuration.dsc.yaml
& .\applications\chatgpt\apply.ps1
& .\applications\git\apply.ps1
& .\applications\vscode\apply.ps1
& .\system\wallpaper\apply.ps1
```
The specialized scripts own the details of their own configuration.
## Packages
### Scoop
`Scoopfile.json` currently declares:
- Git
The update entry point:
1. updates Scoop and bucket metadata
2. imports `Scoopfile.json` so newly declared packages are installed
3. updates all applications installed through Scoop
### WinGet / Microsoft Store
`packages/winget.dsc.yaml` manages:
- Google Chrome
- 1Password
- Visual Studio Code
- Vesktop (`Vencord.Vesktop`)
- 7-Zip
ChatGPT is intentionally not part of this DSC file because its Microsoft Store
installation requires explicit package/source agreement acceptance.
### ChatGPT
`applications/chatgpt/apply.ps1` uses OpenAI's documented WinGet installation:
```powershell
winget install `
--id 9NT1R1C2HH7J `
--source msstore `
--accept-package-agreements `
--accept-source-agreements `
--silent `
--disable-interactivity
```
The Store product ID `9NT1R1C2HH7J` is the ChatGPT Windows app. The previously
used `9PLM9XGG6VKS` ID is not used here.
7-Zip is intentionally installed with its normal Windows installer through
WinGet rather than as a portable Scoop package, because the normal installer
provides Explorer shell integration.
## Windows settings
### Taskbar
`system/taskbar.dsc.yaml` configures:
- Widgets: off
- Resume: off
- Search: icon only
- Alignment: left
### Explorer
`system/explorer.dsc.yaml` configures:
- show known file extensions
7-Zip context-menu integration is left to the official 7-Zip installer. No
unsupported Explorer context-menu patches are applied.
### Microsoft IME
`system/ime.dsc.yaml` configures:
- Muhenkan: IME Off
- Henkan: IME On
## Git
Git's user configuration lives in:
```text
applications/git/gitconfig
```
It currently contains:
```ini
[user]
name = moons-14
email = [email protected]
```
`applications/git/apply.ps1` copies this file to:
```text
%USERPROFILE%\.gitconfig
```
This means the repository is the source of truth for the managed global Git
configuration. Add future Git settings to `applications/git/gitconfig`, not to
`update.ps1`.
## Visual Studio Code
VS Code configuration lives entirely under:
```text
applications/vscode/
```
### `settings.json`
Minimal editor defaults:
- no startup welcome editor
- format on save
- final newline
### `argv.json`
Sets the VS Code UI locale to Japanese:
```json
{
"locale": "ja"
}
```
### `extensions.txt`
One Marketplace extension ID per line.
Currently:
```text
MS-CEINTL.vscode-language-pack-ja
```
`applications/vscode/apply.ps1` copies the config files and uses the official
VS Code CLI. It first checks `code --list-extensions`, installs only missing
declared extensions, then runs `code --update-extensions`.
To add another extension, only edit `extensions.txt`.
## Wallpaper
Wallpaper management lives under:
```text
system/wallpaper/
```
`apply.ps1` synchronizes:
```text
https://github.com/moons-14/wallpapers
```
to:
```text
%USERPROFILE%\.wallpaper
```
The slideshow itself is not implemented in PowerShell.
`wallpaper.theme` uses the native Windows slideshow mechanism:
```ini
[Slideshow]
Interval=60000
Shuffle=1
ImagesRootPath=%USERPROFILE%\.wallpaper
```
Windows therefore performs the one-minute randomized rotation. The script only
keeps the Git repository and theme declaration synchronized.
The theme also contains the required Windows theme validity marker:
```ini
[MasterThemeSelector]
MTSM=DABJDKT
```
Without this section, Windows rejects the `.theme` file instead of applying it.
## Adding an application
### Package only
If it belongs in Scoop `main`, add it to:
```text
Scoopfile.json
```
Otherwise add a `Microsoft.WinGet/Package` resource to:
```text
packages/winget.dsc.yaml
```
No PowerShell file is necessary when installation is the only requirement.
### Package with configuration
If an application needs managed files or its own CLI, create:
```text
applications/<name>/
├── apply.ps1
└── <native configuration files>
```
Then add only one call to the root `update.ps1`:
```powershell
& .\applications\<name>\apply.ps1
```
Keep all application-specific logic inside that directory.
## Adding a Windows setting
Settings that can be represented as DSC belong under `system/` and should be
grouped by responsibility:
```text
system/taskbar.dsc.yaml
system/explorer.dsc.yaml
system/ime.dsc.yaml
system/privacy.dsc.yaml
```
When adding a new DSC document, include it from `configuration.dsc.yaml`.
If a system feature cannot be expressed reliably with DSC and genuinely needs
procedural setup, give that feature its own directory, following the wallpaper
pattern:
```text
system/<feature>/
├── apply.ps1
└── ...
```
Do not add feature-specific logic directly to `update.ps1`.
## Design rules
- Prefer a tool's native declaration/configuration format.
- Prefer DSC for Windows desired state.
- Keep application-specific procedural work beside the application.
- Keep system-specific procedural work beside the system feature.
- Keep `update.ps1` as an orchestration list, not a configuration engine.
- Do not duplicate package lists in PowerShell.
- Avoid background PowerShell loops, Scheduled Tasks, and registry hacks when a
stable application or Windows mechanism already exists.
+15
View File
@@ -0,0 +1,15 @@
{
"buckets": [
{
"Name": "main",
"Source": "https://github.com/ScoopInstaller/Main"
}
],
"apps": [
{
"Name": "git",
"Source": "main",
"Info": ""
}
]
}
+13
View File
@@ -0,0 +1,13 @@
$ErrorActionPreference = "Stop"
winget install `
--id 9PLM9XGG6VKS `
--source msstore `
--accept-package-agreements `
--accept-source-agreements `
--silent `
--disable-interactivity
if ($LASTEXITCODE -ne 0) {
throw "Failed to install or update ChatGPT."
}
+6
View File
@@ -0,0 +1,6 @@
$ErrorActionPreference = "Stop"
$source = Join-Path $PSScriptRoot "gitconfig"
$target = Join-Path $HOME ".gitconfig"
Copy-Item $source $target -Force
+3
View File
@@ -0,0 +1,3 @@
[user]
name = moons-14
email = [email protected]
+54
View File
@@ -0,0 +1,54 @@
$ErrorActionPreference = "Stop"
$userDir = Join-Path $env:APPDATA "Code\User"
$runtimeDir = Join-Path $HOME ".vscode"
New-Item -ItemType Directory -Force -Path $userDir, $runtimeDir | Out-Null
Copy-Item (Join-Path $PSScriptRoot "settings.json") `
(Join-Path $userDir "settings.json") -Force
Copy-Item (Join-Path $PSScriptRoot "argv.json") `
(Join-Path $runtimeDir "argv.json") -Force
$codeCandidates = @(
(Join-Path $env:LOCALAPPDATA "Programs\Microsoft VS Code\bin\code.cmd"),
(Join-Path $env:ProgramFiles "Microsoft VS Code\bin\code.cmd")
)
$code = $codeCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
if (-not $code) {
$command = Get-Command code.cmd -ErrorAction SilentlyContinue
if ($command) {
$code = $command.Source
}
}
if (-not $code) {
throw "VS Code CLI was not found."
}
$installedExtensions = @(
& $code --list-extensions |
ForEach-Object { $_.Trim().ToLowerInvariant() }
)
Get-Content (Join-Path $PSScriptRoot "extensions.txt") |
Where-Object { $_.Trim() -and -not $_.Trim().StartsWith("#") } |
ForEach-Object {
$extension = $_.Trim()
if ($installedExtensions -notcontains $extension.ToLowerInvariant()) {
& $code --install-extension $extension
if ($LASTEXITCODE -ne 0) {
throw "Failed to install VS Code extension: $extension"
}
}
}
& $code --update-extensions
if ($LASTEXITCODE -ne 0) {
throw "Failed to update VS Code extensions."
}
+3
View File
@@ -0,0 +1,3 @@
{
"locale": "ja"
}
@@ -0,0 +1,2 @@
# One Visual Studio Code Marketplace extension ID per line.
MS-CEINTL.vscode-language-pack-ja
@@ -0,0 +1,5 @@
{
"workbench.startupEditor": "none",
"editor.formatOnSave": true,
"files.insertFinalNewline": true
}
+22
View File
@@ -0,0 +1,22 @@
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: WinGet packages
type: Microsoft.DSC/Include
properties:
configurationFile: packages/winget.dsc.yaml
- name: Taskbar
type: Microsoft.DSC/Include
properties:
configurationFile: system/taskbar.dsc.yaml
- name: Explorer
type: Microsoft.DSC/Include
properties:
configurationFile: system/explorer.dsc.yaml
- name: Microsoft IME
type: Microsoft.DSC/Include
properties:
configurationFile: system/ime.dsc.yaml
+37
View File
@@ -0,0 +1,37 @@
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: Google Chrome
type: Microsoft.WinGet/Package
properties:
id: Google.Chrome
source: winget
useLatest: true
- name: 1Password
type: Microsoft.WinGet/Package
properties:
id: AgileBits.1Password
source: winget
useLatest: true
- name: Visual Studio Code
type: Microsoft.WinGet/Package
properties:
id: Microsoft.VisualStudioCode
source: winget
useLatest: true
- name: Vesktop
type: Microsoft.WinGet/Package
properties:
id: Vencord.Vesktop
source: winget
useLatest: true
- name: 7-Zip
type: Microsoft.WinGet/Package
properties:
id: 7zip.7zip
source: winget
useLatest: true
+11
View File
@@ -0,0 +1,11 @@
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: Show file extensions
type: Microsoft.Windows/Registry
properties:
keyPath: HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
valueName: HideFileExt
valueData:
DWord: 0
_exist: true
+29
View File
@@ -0,0 +1,29 @@
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: IME Key Assignment
type: Microsoft.Windows/Registry
properties:
keyPath: HKCU\Software\Microsoft\IME\15.0\IMEJP\MSIME
valueName: IsKeyAssignmentEnabled
valueData:
DWord: 1
_exist: true
- name: Muhenkan IME Off
type: Microsoft.Windows/Registry
properties:
keyPath: HKCU\Software\Microsoft\IME\15.0\IMEJP\MSIME
valueName: KeyAssignmentMuhenkan
valueData:
DWord: 1
_exist: true
- name: Henkan IME On
type: Microsoft.Windows/Registry
properties:
keyPath: HKCU\Software\Microsoft\IME\15.0\IMEJP\MSIME
valueName: KeyAssignmentHenkan
valueData:
DWord: 0
_exist: true
+38
View File
@@ -0,0 +1,38 @@
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: Taskbar Widgets
type: Microsoft.Windows/Registry
properties:
keyPath: HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
valueName: TaskbarDa
valueData:
DWord: 0
_exist: true
- name: Taskbar Resume
type: Microsoft.Windows/Registry
properties:
keyPath: HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
valueName: IsEnabled
valueData:
DWord: 0
_exist: true
- name: Taskbar Search
type: Microsoft.Windows/Registry
properties:
keyPath: HKCU\Software\Microsoft\Windows\CurrentVersion\Search
valueName: SearchboxTaskbarMode
valueData:
DWord: 1
_exist: true
- name: Taskbar Alignment
type: Microsoft.Windows/Registry
properties:
keyPath: HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
valueName: TaskbarAl
valueData:
DWord: 0
_exist: true
+32
View File
@@ -0,0 +1,32 @@
$ErrorActionPreference = "Stop"
$wallpaperDir = Join-Path $HOME ".wallpaper"
if (Test-Path (Join-Path $wallpaperDir ".git")) {
git -C $wallpaperDir pull --ff-only
}
elseif (-not (Test-Path $wallpaperDir)) {
git clone https://github.com/moons-14/wallpapers.git $wallpaperDir
}
else {
throw "$wallpaperDir exists but is not a Git repository."
}
if ($LASTEXITCODE -ne 0) {
throw "Failed to synchronize the wallpaper repository."
}
$themeDir = Join-Path $env:LOCALAPPDATA "Microsoft\Windows\Themes"
$themeTarget = Join-Path $themeDir "moons-wallpaper.theme"
New-Item -ItemType Directory -Force -Path $themeDir | Out-Null
Copy-Item (Join-Path $PSScriptRoot "wallpaper.theme") $themeTarget -Force
$currentTheme = (Get-ItemProperty `
"HKCU:\Software\Microsoft\Windows\CurrentVersion\Themes" `
-Name CurrentTheme `
-ErrorAction SilentlyContinue).CurrentTheme
if ($currentTheme -ne $themeTarget) {
Start-Process $themeTarget
}
+21
View File
@@ -0,0 +1,21 @@
[Theme]
DisplayName=Moons Wallpapers
[Slideshow]
Interval=60000
Shuffle=1
ImagesRootPath=%USERPROFILE%\.wallpaper
[Control Panel\Desktop]
TileWallpaper=0
WallpaperStyle=10
Pattern=
[VisualStyles]
Path=%SystemRoot%\resources\themes\Aero\Aero.msstyles
ColorStyle=NormalColor
Size=NormalSize
Transparency=1
[MasterThemeSelector]
MTSM=DABJDKT
+19
View File
@@ -0,0 +1,19 @@
$ErrorActionPreference = "Stop"
Push-Location $PSScriptRoot
try {
scoop update
scoop import .\Scoopfile.json
scoop update *
dsc config set --file .\configuration.dsc.yaml
& .\applications\chatgpt\apply.ps1
& .\applications\git\apply.ps1
& .\applications\vscode\apply.ps1
& .\system\wallpaper\apply.ps1
}
finally {
Pop-Location
}