Generate comprehensive Mac environment inventory and restoration guide
Generates comprehensive Mac environment inventory and restoration guide with cloud backup options.
/plugin marketplace add ksk-incom/MacInventory/plugin install macinventory@macinventory-marketplaceYou'll be guided through the process with questionsGenerate a comprehensive inventory of the Mac computing environment including applications, packages, configurations, and optionally create a professional restoration guide.
First, use AskUserQuestion to display the runtime notice and get user confirmation:
If the user selects "Cancel": Stop immediately and confirm the inventory was cancelled.
If the user selects "Yes, start inventory": Create the todo list and proceed to Phase 1.
IMMEDIATELY after the user confirms, you MUST use the TodoWrite tool to create a todo list with all phases. This is mandatory - do not skip this step.
Create these todos (mark the first one as in_progress, the rest as pending):
| # | Content | Active Form |
|---|---|---|
| 1 | Discover plugin location and check for updates | Discovering plugin location |
| 2 | Check prerequisites | Checking prerequisites |
| 3 | Gather user preferences | Gathering user preferences |
| 4 | Create output directory and configuration | Creating output directory |
| 5 | Execute inventory scan | Running inventory scan |
| 6 | Post-process: validate configs and generate guide | Post-processing inventory |
| 7 | Sync to cloud storage (if selected) | Syncing to cloud storage |
| 8 | Report final results | Reporting results |
Update the todo list as you complete each phase:
in_progress when starting itcompleted when donecompleted with a noteBefore running any Python scripts, discover the plugin's installation path and check for updates.
Method 1: Check installed_plugins.json (for installed plugins)
Run this bash command to get the install path and version:
python3 -c "
import json, os
try:
with open(os.path.expanduser('~/.claude/plugins/installed_plugins.json')) as f:
plugins = json.load(f)['plugins']
for key, value in plugins.items():
if 'macinventory' in key.lower():
data = value[0]
print(f\"{data['installPath']}|{data.get('version', 'unknown')}\")
break
except: pass
"
Output format: /path/to/plugin|1.1.10
Parse the output to extract:
||If this returns a valid path (non-empty), proceed to Step 1b.
Method 2: Glob fallback (for development mode)
If Method 1 returns empty or the path doesn't exist, use Glob to search:
Pattern: **/macinventory/python/main.py
Then extract PLUGIN_ROOT by removing /python/main.py from the found path.
Note: In development mode (Method 2), skip the update check and proceed directly to Phase 2.
Store PLUGIN_ROOT for use in subsequent phases. If neither method finds the plugin, report error: "MacInventory plugin files not found. Please reinstall the plugin."
Use WebFetch to get the latest version from GitHub:
https://raw.githubusercontent.com/ksk-incom/MacInventory/main/VERSIONThe response will be a version string like 1.1.12.
Compare versions:
If WebFetch fails (network error, timeout, etc.):
If WebFetch succeeds:
If remote version > installed version:
Use AskUserQuestion:
If user selects "Update now":
Run the update script:
bash [PLUGIN_ROOT]/scripts/update-plugin.sh
(Replace [PLUGIN_ROOT] with the path discovered in Step 1a)
After the script completes, inform the user:
"Update complete! Please restart Claude Code for the changes to take effect, then run /inventory again."
Then STOP the inventory process.
If user selects "Continue with current version":
If versions are equal or installed is newer:
Before starting, validate the system environment using the prerequisites-checker agent:
Use the Task tool to spawn the prerequisites-checker agent:
macinventory:prerequisites-checkerCheck all prerequisites for MacInventory and report status. Plugin root: [PLUGIN_ROOT](Replace [PLUGIN_ROOT] with the actual path discovered in Phase 1)
The agent will return a clean summary of available and missing tools.
If all tools are available: Proceed to Phase 3.
If any tools are missing (required OR optional):
Use AskUserQuestion to offer installation:
If user selects "Yes, install missing tools":
Install each missing tool using the appropriate command:
| Tool | Installation Command |
|---|---|
| PyYAML | pip3 install pyyaml |
| Homebrew | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" |
| mas | brew install mas (requires Homebrew) |
After installation attempts, re-run the prerequisites-checker agent to verify:
If user selects "No, continue without them":
If user selects "Cancel inventory": Stop immediately and confirm the inventory was cancelled.
Run the cloud storage detection FIRST, so all questions can be asked in a single prompt:
python3 [PLUGIN_ROOT]/python/utils/storage_detection.py --json
(Replace [PLUGIN_ROOT] with the path discovered in Phase 1)
The output is a JSON object mapping service names to their FULL PATHS, e.g.:
{"OneDrive": "/Users/username/Library/CloudStorage/OneDrive-AccountName"}
Store the detected services for use in the questions below.
Use ONE AskUserQuestion call with all questions. The AskUserQuestion tool supports up to 4 questions in a single call.
Question 1 - Security Settings:
Question 2 - Guide Generation:
Question 3 - Cloud Backup Destination (only if cloud storage was detected):
CRITICAL: When the user selects a cloud service, save the FULL PATH from the detection output (e.g., /Users/username/Library/CloudStorage/OneDrive-AccountName) to config.json, NOT just the service name.
If no cloud storage was detected: Only ask Questions 1 and 2 (omit Question 3 entirely).
After collecting preferences, create a timestamped output directory and configuration file:
# Generate timestamp for unique directory name
TIMESTAMP=$(date +%Y-%m-%d-%H%M%S)
OUTPUT_DIR=~/mac-inventory/$TIMESTAMP
# Create output directory
mkdir -p "$OUTPUT_DIR"
# Create config file in the output directory
cat > "$OUTPUT_DIR/config.json" << 'EOF'
{
"output_dir": "$OUTPUT_DIR",
"include_secrets": [true/false based on security choice],
"cloud_destination": "[full path to cloud storage or null if skipped]",
"generate_guide": [true/false based on guide generation choice]
}
EOF
IMPORTANT: The cloud_destination field must contain the FULL PATH to the cloud storage directory (e.g., /Users/username/Library/CloudStorage/OneDrive-AccountName/), NOT just the service name. Use null (without quotes) if the user skipped cloud backup. The generate_guide field tracks whether to generate the Restoration-Guide.md.
Run the Python backend to perform the inventory:
python3 -u [PLUGIN_ROOT]/python/main.py "$OUTPUT_DIR/config.json"
(Replace [PLUGIN_ROOT] with the path discovered in Phase 1)
Monitor the output and report progress to the user:
After the inventory completes, perform these sub-agent orchestrations:
Read the undiscovered_report.yaml file (if present) to check for apps without known config paths:
cat [output_dir]/undiscovered_report.yaml 2>/dev/null || echo "No undiscovered apps report"
If unknown apps exist, ask the user:
For unknown apps, spawn app-discovery agents IN PARALLEL using batches of 5:
Example with 12 unknown apps:
First batch - Spawn 5 agents in parallel using multiple Task tool calls in a SINGLE message:
Use the Task tool 5 times with these prompts:
subagent_type='app-discovery', prompt='Research config paths for Obsidian (bundle_id: md.obsidian). Return YAML entry for app-hints.yaml.'subagent_type='app-discovery', prompt='Research config paths for Arc (bundle_id: company.thebrowser.Browser). Return YAML entry for app-hints.yaml.'subagent_type='app-discovery', prompt='Research config paths for Linear. Return YAML entry for app-hints.yaml.'subagent_type='app-discovery', prompt='Research config paths for Raycast. Return YAML entry for app-hints.yaml.'subagent_type='app-discovery', prompt='Research config paths for Warp. Return YAML entry for app-hints.yaml.'Wait for all 5 agents to complete and collect results
Second batch - Repeat with next 5 apps (agents 6-10)
Final batch - Process remaining 2 apps (agents 11-12)
Merge results - Collect all discovered YAML entries from all batches
CRITICAL: Parallel spawning requires using multiple Task tool invocations in a SINGLE message. Do not send separate messages for each agent.
After inventory and any app research, spawn the config-validator agent:
"Validate the backed up configs at [output_dir]/configs/ for quality and security. Check for leaked secrets, invalid file formats, and completeness. Plugin root: [PLUGIN_ROOT]"
(Replace [PLUGIN_ROOT] with the path discovered in Phase 1)
If the user requested guide generation, spawn the guide-generator agent:
"Generate a comprehensive Restoration-Guide.md for the Mac inventory at [output_dir]. Read state.yaml and the backed-up configs to create professional restoration documentation."
After all processing, spawn the verification agent:
"Verify the inventory output at [output_dir] including state.yaml, Brewfile, and all generated files for completeness and quality."
Read the cloud_destination from config.json to determine if cloud backup was requested:
# Read cloud destination from config.json
CLOUD_PATH=$(python3 -c "import json; c=json.load(open('[output_dir]/config.json')); print(c.get('cloud_destination') or '')")
if [ -n "$CLOUD_PATH" ]; then
# Extract timestamp from output directory to mirror local structure
# Local: ~/mac-inventory/YYYY-MM-DD-HHMMSS/
# Cloud: [cloud_path]/mac-inventory/YYYY-MM-DD-HHMMSS/
TIMESTAMP=$(basename [output_dir])
CLOUD_DEST="$CLOUD_PATH/mac-inventory/$TIMESTAMP"
mkdir -p "$CLOUD_DEST"
# Copy all output files
cp -R [output_dir]/* "$CLOUD_DEST/"
echo "Inventory backed up to: $CLOUD_DEST"
else
echo "Cloud backup skipped (not selected)"
fi
Report the cloud backup location to the user.
Provide a comprehensive summary to the user:
Inventory Summary:
Output Files Created:
state.yaml - Complete system state snapshotbundles/Brewfile - Homebrew restoration filebundles/ - Package lists for npm, pip, etc.configs/ - Backed up configuration filesRestoration-Guide.md - (if requested) Step-by-step restoration guideundiscovered_report.yaml - Apps without known config paths (if any)Validation Results:
Cloud Backup:
Next Steps:
If prerequisites fail:
pip3 install pyyaml/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"brew install masIf the Python backend fails:
python3 --versionpython3 -c "import yaml"If an agent fails:
If parallel spawning fails: