用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/tomevault-io/skills-registry --skill device-profile-management命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
| Use when this capability is needed.
> Use when this capability is needed.
Review architecture and API design for the vfs-s3 project. Use when the user mentions @architect, asks to review an issue's design, discuss module boundaries, API shape, or architectural decisions for vfs-s3. Also trigger when the user wants to create an ADR (Architecture Decision Record) or evaluate a technical approach for the project. Intended for dispatch from Codex automation or Claude routines; GitHub trigger phrase: @vfs-s3-bot please prepare design doc Use when this capability is needed.
基于 SOC 职业分类
正在显示 SKILL.md
| name | device-profile-management |
| description | | Use when this capability is needed. |
.env files or credentials inside any skill folder..env.template files belong only in templates/ within a skill.~/.admin/.env (or another non-skill location you control) and reference them from there.Status: Production Ready Last Updated: 2025-12-06 Dependencies: winadmin-powershell skill Sync Options: Dropbox, OneDrive, Network Share, Local
Choose a centralized location accessible from all devices:
# Option A: Dropbox
$adminRoot = "N:/Dropbox/Admin"
# Option B: OneDrive
$adminRoot = "$env:USERPROFILE/OneDrive/Admin"
# Option C: Network Share
$adminRoot = "\\server\share\Admin"
# Option D: Local only
$adminRoot = "D:/Admin"
# Create admin structure
$adminRoot = "N:/Dropbox/Admin" # Change to your path
New-Item -ItemType Directory -Path "$adminRoot/devices/$env:COMPUTERNAME" -Force
New-Item -ItemType Directory -Path "$adminRoot/logs/central" -Force
New-Item -ItemType Directory -Path "$adminRoot/registries" -Force
New-Item -ItemType Directory -Path "$adminRoot/configs" -Force
# Create initial files
@{} | ConvertTo-Json | Set-Content "$adminRoot/devices/$env:COMPUTERNAME/profile.json"
"" | Set-Content "$adminRoot/devices/$env:COMPUTERNAME/logs.txt"
"" | Set-Content "$adminRoot/logs/central/operations.log"
"" | Set-Content "$adminRoot/logs/central/installations.log"
"" | Set-Content "$adminRoot/logs/central/system-changes.log"
# Run initialization script
.\scripts\Initialize-DeviceProfile.ps1 -AdminRoot $adminRoot
yyyy-MM-ddTHH:mm:ssZ)profile_new.json, profile_backup.json)Admin/ # ADMIN_ROOT
├── devices/ # Per-device data
│ ├── DEVICE1/
│ │ ├── profile.json # Device profile (source of truth)
│ │ └── logs.txt # Device-specific operations log
│ ├── DEVICE2/
│ │ ├── profile.json
│ │ └── logs.txt
│ └── .../
├── logs/
│ └── central/ # Cross-device logs
│ ├── operations.log # General operations
│ ├── installations.log # Software installations
│ └── system-changes.log # Configuration changes
├── registries/
│ └── mcp-registry.json # MCP server registry
└── configs/
└── shared-settings.json # Cross-device settings
{
"schemaVersion": "1.0",
"deviceInfo": {
"name": "DEVICE_NAME",
"os": "Windows 11 Professional",
"osVersion": "10.0.22631",
"lastUpdated": "2025-12-06T12:00:00Z",
"adminRoot": "N:/Dropbox/Admin",
"timezone": "America/New_York"
},
"packageManagers": {
"winget": {
"present": true,
"version": "1.9.25200",
"lastChecked": "2025-12-06T12:00:00Z",
"location": "C:/Users/Owner/AppData/Local/Microsoft/WindowsApps/winget.exe"
}
Each tool in installedTools follows this schema:
{
"present": true, // Required: Is tool currently installed?
"version": "1.2.3", // Required: Version string or null
"lastChecked": "ISO8601", // Required: When was this last verified?
"installedVia": "winget", // Required: winget|scoop|npm|chocolatey|manual
"installStatus": "failed", // Optional: Only if not success
"path": "/path/to/exe", // Optional: Full path to executable
"shimPath": "/path/shim", // Optional: Shim path (scoop/npm)
"notes": "Additional info" // Optional: Context or issues
}
{
"date": "2025-12-06", // Required: ISO date
"action": "install", // Required: install|upgrade|uninstall|repair
"tool": "tool-name", // Required: Tool identifier
"method": "winget", // Required: Installation method
"version": "1.2.3", // Required: Version installed
"previousVersion": "1.2.0", // Optional: For upgrades
"status": "success", // Required: success|failed|partial
"details": "Description" // Optional: Additional context
}
function Get-DeviceProfile {
param(
[string]$AdminRoot = $env:ADMIN_ROOT,
[string]$DeviceName = $env:COMPUTERNAME
)
$profilePath = "$AdminRoot/devices/$DeviceName/profile.json"
if (Test-Path $profilePath) {
Get-Content $profilePath -Raw | ConvertFrom-Json
} else {
Write-Warning "Profile not found: $profilePath"
$null
}
}
# Usage
$profile = Get-DeviceProfile
$profile.installedTools.git.version
function Update-DeviceProfile {
param(
[Parameter(Mandatory)]
[scriptblock]$UpdateScript,
[string]$AdminRoot = $env:ADMIN_ROOT,
[string]$DeviceName = $env:COMPUTERNAME
)
$profilePath = "$AdminRoot/devices/$DeviceName/profile.json"
# Read existing profile
$profile = Get-Content $profilePath -Raw | ConvertFrom-Json
# Apply updates
& $UpdateScript $profile
# Update timestamp
$profile.deviceInfo.lastUpdated = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ")
# Save back to SAME file
$profile | ConvertTo-Json -Depth 10 | Set-Content $profilePath
Write-Host "Profile updated: $profilePath" -ForegroundColor Green
}
# Usage - Update a tool
Update-DeviceProfile -UpdateScript {
param($p)
$p.installedTools.node.version = "22.12.0"
$p.installedTools.node.lastChecked = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ")
}
function Add-InstallationHistory {
param(
[Parameter(Mandatory)][string]$Tool,
[Parameter(Mandatory)][string]$Action,
[Parameter(Mandatory)][string]$Method,
[Parameter(Mandatory)][string]$Version,
[string]$PreviousVersion,
[ValidateSet("success", "failed", "partial")]
[string]$Status = "success",
[string]$Details,
[string]$AdminRoot = $env:ADMIN_ROOT,
[string]$DeviceName = $env:COMPUTERNAME
)
$profilePath = "$AdminRoot/devices/$DeviceName/profile.json"
$profile = Get-Content $profilePath -Raw | ConvertFrom-Json
$entry = [ordered]@{
date = (Get-Date -Format "yyyy-MM-dd")
action = $Action
tool = $Tool
method = $Method
version = $Version
status = $Status
}
if ($PreviousVersion) { $entry.previousVersion = $PreviousVersion }
if ($Details) { $entry.details = $Details }
# Append to history
$profile.installationHistory += [PSCustomObject]$entry
# Update timestamp
$profile.deviceInfo.lastUpdated = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ")
# Save
$profile | ConvertTo-Json -Depth 10 | Set-Content $profilePath
Write-Host "Added to history: $Action $Tool $Version" -ForegroundColor Green
}
# Usage
Add-InstallationHistory -Tool "claude" -Action "upgrade" -Method "npm" `
-Version "1.0.18" -PreviousVersion "1.0.17" `
-Details "npm update -g @anthropic-ai/claude-code"
function Test-ToolInstallation {
param(
[Parameter(Mandatory)][string]$Tool,
[string]$AdminRoot = $env:ADMIN_ROOT,
[string]$DeviceName = $env:COMPUTERNAME
)
$profile = Get-DeviceProfile -AdminRoot $AdminRoot -DeviceName $DeviceName
$toolInfo = $profile.installedTools.$Tool
if (-not $toolInfo) {
Write-Host "Tool not in profile: $Tool" -ForegroundColor Yellow
return $false
}
# Check if command exists
$cmd = Get-Command $Tool -ErrorAction SilentlyContinue
$result = [PSCustomObject]@{
Tool = $Tool
ProfileSaysPresent = $toolInfo.present
ActuallyPresent = $null -ne $cmd
ProfileVersion = $toolInfo.version
ActualVersion = $null
Match = $false
}
if ($cmd) {
try {
$result.ActualVersion = & $Tool --version 2>&1 | Select-Object -First 1
} catch {}
}
$result.Match = $result.ProfileSaysPresent -eq $result.ActuallyPresent
$result
}
# Usage
Test-ToolInstallation -Tool "git"
Test-ToolInstallation -Tool "node"
| Log File | Location | Purpose |
|---|---|---|
| Device Log | devices/{DEVICE}/logs.txt | All operations on this device |
| Operations Log | logs/central/operations.log | General operations (all devices) |
| Installations Log | logs/central/installations.log | Software installations only |
| System Changes Log | logs/central/system-changes.log | Config/registry changes |
YYYY-MM-DD HH:MM:SS - [DEVICE_NAME] STATUS: Operation - Details
Example entries:
2025-12-06 14:30:15 - [WOPR3] SUCCESS: Install - Installed git via winget
2025-12-06 14:31:00 - [WOPR3] ERROR: Install - Python installation failed
2025-12-06 14:32:00 - [DELTABOT] INFO: Session Start - WinAdmin initialized
2025-12-06 14:35:00 - [WOPR3] SUCCESS: Profile Update - Added claude to profile
function Log-Operation {
param(
[Parameter(Mandatory)]
[ValidateSet("SUCCESS", "ERROR", "INFO", "PENDING", "WARNING")]
[string]$Status,
[Parameter(Mandatory)]
[string]$Operation,
[Parameter(Mandatory)]
[string]$Details,
[ValidateSet("operation", "installation", "system-change")]
[string]$LogType = "operation",
[string]$AdminRoot = $env:ADMIN_ROOT,
[string]$DeviceName = $env:COMPUTERNAME
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logEntry = "$timestamp - [$DeviceName] $Status: $Operation - $Details"
# Always log to device log
$deviceLog = "$AdminRoot/devices/$DeviceName/logs.txt"
if (Test-Path (Split-Path $deviceLog)) {
Add-Content $deviceLog -Value $logEntry
}
# Log to appropriate central log
$centralLogDir = "$AdminRoot/logs/central"
if (Test-Path $centralLogDir) {
$centralLog = switch ($LogType) {
"installation" { "$centralLogDir/installations.log" }
"system-change" { "$centralLogDir/system-changes.log" }
default { "$centralLogDir/operations.log" }
}
Add-Content $centralLog -Value $logEntry
}
# Console output with color
$color = switch ($Status) {
"SUCCESS" { "Green" }
"ERROR" { "Red" }
"WARNING" { "Yellow" }
"PENDING" { "Cyan" }
default { "White" }
}
Write-Host $logEntry -ForegroundColor $color
}
# Usage examples
Log-Operation -Status "SUCCESS" -Operation "Install" -Details "Installed git 2.47.0 via winget" -LogType "installation"
Log-Operation -Status "ERROR" -Operation "Install" -Details "Python installation failed: scoop error" -LogType "installation"
Log-Operation -Status "INFO" -Operation "Session" -Details "WinAdmin session started"
Log-Operation -Status "SUCCESS" -Operation "Config" -Details "Updated PATH in registry" -LogType "system-change"
function Get-RecentLogs {
param(
[int]$Lines = 20,
[ValidateSet("device", "operations", "installations", "system-changes", "all")]
[string]$LogType = "device",
[string]$AdminRoot = $env:ADMIN_ROOT,
[string]$DeviceName = $env:COMPUTERNAME
)
$logs = switch ($LogType) {
"device" { @("$AdminRoot/devices/$DeviceName/logs.txt") }
"operations" { @("$AdminRoot/logs/central/operations.log") }
"installations" { @("$AdminRoot/logs/central/installations.log") }
"system-changes" { @("$AdminRoot/logs/central/system-changes.log") }
"all" {
@(
"$AdminRoot/devices/$DeviceName/logs.txt",
"$AdminRoot/logs/central/operations.log",
"$AdminRoot/logs/central/installations.log",
"$AdminRoot/logs/central/system-changes.log"
)
}
}
foreach ($log in $logs) {
if (Test-Path $log) {
Write-Host "`n=== $(Split-Path $log -Leaf) ===" -ForegroundColor Cyan
Get-Content $log -Tail $Lines
}
}
}
# Usage
Get-RecentLogs -Lines 10 -LogType "device"
Get-RecentLogs -Lines 50 -LogType "all"
| Strategy | Pros | Cons | Best For |
|---|---|---|---|
| Dropbox | Automatic sync, conflict handling | Requires Dropbox | Personal/small team |
| OneDrive | Windows integration | May have sync delays | Microsoft ecosystem |
| Network Share | Fast LAN access | No offline access | Enterprise/LAN |
| Git | Version history, branches | Manual sync | Developers |
function Resolve-ProfileConflict {
param(
[string]$AdminRoot = $env:ADMIN_ROOT,
[string]$DeviceName = $env:COMPUTERNAME
)
$profilePath = "$AdminRoot/devices/$DeviceName/profile.json"
$conflictPattern = "$AdminRoot/devices/$DeviceName/profile*.json"
$conflicts = Get-ChildItem $conflictPattern | Where-Object {
$_.Name -ne "profile.json"
}
if ($conflicts.Count -eq 0) {
Write-Host "No conflicts found" -ForegroundColor Green
return
}
Write-Host "Found $($conflicts.Count) conflict files:" -ForegroundColor Yellow
$conflicts | ForEach-Object { Write-Host " - $($_.Name)" }
# Strategy: Keep newest, merge installation history
$main = Get-Content $profilePath -Raw | ConvertFrom-Json
$mainTime = [DateTime]::Parse($main.deviceInfo.lastUpdated)
foreach ($conflict in $conflicts) {
$other = Get-Content $conflict.FullName -Raw | ConvertFrom-Json
$otherTime = [DateTime]::Parse($other.deviceInfo.lastUpdated)
# Merge installation history (deduplicate by date+tool+action)
$existingKeys = $main.installationHistory | ForEach-Object {
"$($_.date)-$($_.tool)-$($_.action)"
}
foreach ($entry in $other.installationHistory) {
$key = "$($entry.date)-$($entry.tool)-$($entry.action)"
if ($key -notin $existingKeys) {
$main.installationHistory += $entry
Write-Host " Merged history entry: $key" -ForegroundColor Gray
}
}
# Use newer tool versions
if ($otherTime -gt $mainTime) {
foreach ($tool in $other.installedTools.PSObject.Properties) {
$main.installedTools.($tool.Name) = $tool.Value
}
Write-Host " Used newer tool info from conflict file" -ForegroundColor Gray
}
# Remove conflict file
Remove-Item $conflict.FullName
Write-Host " Removed: $($conflict.Name)" -ForegroundColor Gray
}
# Sort installation history by date
$main.installationHistory = $main.installationHistory | Sort-Object date
# Save merged profile
$main.deviceInfo.lastUpdated = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ")
$main | ConvertTo-Json -Depth 10 | Set-Content $profilePath
Write-Host "Conflicts resolved!" -ForegroundColor Green
}
function Compare-DeviceProfiles {
param(
[string]$AdminRoot = $env:ADMIN_ROOT
)
$devices = Get-ChildItem "$AdminRoot/devices" -Directory
$comparison = @()
foreach ($device in $devices) {
$profilePath = "$($device.FullName)/profile.json"
if (Test-Path $profilePath) {
$profile = Get-Content $profilePath -Raw | ConvertFrom-Json
foreach ($tool in $profile.installedTools.PSObject.Properties) {
$comparison += [PSCustomObject]@{
Device = $device.Name
Tool = $tool.Name
Present = $tool.Value.present
Version = $tool.Value.version
LastChecked = $tool.Value.lastChecked
}
}
}
}
# Pivot to show tool versions across devices
$tools = $comparison | Select-Object -ExpandProperty Tool -Unique
Write-Host "`n=== Tool Versions Across Devices ===" -ForegroundColor Cyan
foreach ($tool in $tools) {
Write-Host "`n$tool`:" -ForegroundColor Yellow
$comparison | Where-Object { $_.Tool -eq $tool } | ForEach-Object {
$status = if ($_.Present) { $_.Version } else { "[not installed]" }
Write-Host " $($_.Device): $status"
}
}
}
Error: Multiple profile files causing confusion
Prevention: Always update profile.json directly, never create copies
Error: History entries disappearing Prevention: Always append to history, never replace array
Error: Date parsing failures
Prevention: Always use ISO 8601: yyyy-MM-ddTHH:mm:ssZ
Error: Lost changes after sync Prevention: Use conflict resolution function, merge histories
Error: Operations not logged
Prevention: Always call Log-Operation for every action
Initialize-DeviceProfile.ps1 - Set up new device
.\scripts\Initialize-DeviceProfile.ps1 -AdminRoot "N:/Dropbox/Admin"
Sync-DeviceProfile.ps1 - Verify and update profile
.\scripts\Sync-DeviceProfile.ps1
Export-ProfileReport.ps1 - Generate device report
.\scripts\Export-ProfileReport.ps1 -OutputFile "device-report.md"
profile.json - Complete profile templatedevice-structure/ - Directory structure templatedevices/{DEVICE_NAME}/){
"schemaVersion": "1.0",
"requiredPowerShell": "7.0+"
}
Converted and distributed by TomeVault — claim your Tome and manage your conversions.