{
  "schemaVersion": "1.0",
  "item": {
    "slug": "portable-tools",
    "name": "Portable Tools",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/TunaIssaCoding/portable-tools",
    "canonicalUrl": "https://clawhub.ai/TunaIssaCoding/portable-tools",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/portable-tools",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=portable-tools",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "README.md",
      "SKILL.md",
      "pre-publish-checklist.sh"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/portable-tools"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/portable-tools",
    "agentPageUrl": "https://openagent3.xyz/skills/portable-tools/agent",
    "manifestUrl": "https://openagent3.xyz/skills/portable-tools/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/portable-tools/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Portable Tools - Cross-Device Development Methodology",
        "body": "Methodology for building tools that work across different devices, naming schemes, and configurations. Based on lessons from OAuth refresher debugging session (2026-01-23)."
      },
      {
        "title": "Core Principle",
        "body": "Never assume your device is the only device.\n\nYour local setup is just one of many possible configurations. Build for the general case, not the specific instance."
      },
      {
        "title": "1. \"What varies between devices?\"",
        "body": "Before writing any code that reads configuration, data, or credentials:\n\nAsk:\n\nFile paths? (macOS vs Linux, different home dirs)\nAccount names? (user123 vs default vs oauth)\nService names? (slight variations in spelling/capitalization)\nData structure? (different versions, different formats)\nEnvironment? (different shells, different tools available)\n\nExample from OAuth refresher:\n\n❌ Assumed: Account is always \"claude\"\n✅ Reality: Could be \"claude\", \"Claude Code\", \"default\", etc.\n\nAction: List variables, make them configurable or auto-discoverable"
      },
      {
        "title": "2. \"How do I prove this works?\"",
        "body": "Before claiming success:\n\nRequire:\n\nConcrete BEFORE state (exact values)\nConcrete AFTER state (exact values)\nProof they're different (side-by-side comparison)\n\nExample from OAuth refresher:\n\nBEFORE:\n- Access Token: POp5z1fi...eSN9VAAA\n- Expires: 1769189639000\n\nAFTER:\n- Access Token: 01v0RrFG...eOE9QAA ✅ Different\n- Expires: 1769190268000 ✅ Extended\n\nAction: Always show data transformation with real values"
      },
      {
        "title": "3. \"What happens when it breaks?\"",
        "body": "Before pushing to production:\n\nTest:\n\nWrong configuration (intentionally break config)\nMissing data (remove expected fields)\nMultiple entries (ambiguous case)\nEdge cases (empty values, special characters)\n\nExample from OAuth refresher:\n\nTest with keychain_account: \"wrong-name\" → Fallback should work\nTest with incomplete keychain data → Should fail gracefully with helpful error\n\nAction: Test failure modes, not just happy path"
      },
      {
        "title": "Pattern 1: Explicit Over Implicit",
        "body": "❌ Wrong:\n\n# Ambiguous - returns first match\nsecurity find-generic-password -s \"Service\" -w\n\n✅ Correct:\n\n# Explicit - returns specific entry\nsecurity find-generic-password -s \"Service\" -a \"account\" -w\n\nRule: If a command can be ambiguous, make it explicit."
      },
      {
        "title": "Pattern 2: Validate Before Use",
        "body": "❌ Wrong:\n\nDATA=$(read_config)\nUSE_VALUE=\"$DATA\"  # Hope it's valid\n\n✅ Correct:\n\nDATA=$(read_config)\nif ! validate_structure \"$DATA\"; then\n    error \"Invalid data structure\"\nfi\nUSE_VALUE=\"$DATA\"\n\nRule: Never assume data has expected structure."
      },
      {
        "title": "Pattern 3: Fallback Chains",
        "body": "❌ Wrong:\n\nACCOUNT=\"claude\"  # Hardcoded\n\n✅ Correct:\n\n# Try configured → Try common → Error with help\nACCOUNT=\"${CONFIG_ACCOUNT}\"\nif ! has_data \"$ACCOUNT\"; then\n    for fallback in \"claude\" \"default\" \"oauth\"; do\n        if has_data \"$fallback\"; then\n            ACCOUNT=\"$fallback\"\n            break\n        fi\n    done\nfi\n[[ -z \"$ACCOUNT\" ]] && error \"No account found. Tried: ...\"\n\nRule: Provide automatic fallbacks for common variations."
      },
      {
        "title": "Pattern 4: Helpful Errors",
        "body": "❌ Wrong:\n\n[[ -z \"$TOKEN\" ]] && error \"No token\"\n\n✅ Correct:\n\n[[ -z \"$TOKEN\" ]] && error \"No token found\n\nChecked:\n- Config: $CONFIG_FILE\n- Field: $FIELD_NAME\n- Expected: { \\\"tokens\\\": { \\\"refresh\\\": \\\"...\\\" } }\n\nVerify with:\n  cat $CONFIG_FILE | jq '.tokens'\n\"\n\nRule: Error messages should help user diagnose and fix."
      },
      {
        "title": "Step 1: Get Exact Data",
        "body": "Don't ask: \"Is it broken?\"\nAsk: \"What exact values do you see? How many entries exist? Which one has the data?\"\n\nExample:\n\n# Vague\n\"Check keychain\"\n\n# Specific\n\"Run: security find-generic-password -l 'Service' | grep 'acct'\"\n\"Tell me: 1. How many entries 2. Which has tokens 3. Last modified\""
      },
      {
        "title": "Step 2: Prove With Concrete Examples",
        "body": "Don't say: \"It should work now\"\nShow: \"Here's the BEFORE token (POp5z...), here's AFTER (01v0R...), they're different\"\n\nTemplate:\n\nBEFORE:\n- Field1: <exact_value>\n- Field2: <exact_value>\n\nAFTER:\n- Field1: <new_value> ✅ Changed\n- Field2: <new_value> ✅ Changed\n\nPROOF: Values are different"
      },
      {
        "title": "Step 3: Think Cross-Device Immediately",
        "body": "Don't think: \"Works on my machine\"\nThink: \"What if their setup differs in [X]?\"\n\nChecklist:\n\nDifferent account names?\n Different file paths?\n Different tools/versions?\n Different permissions?\n Different data formats?"
      },
      {
        "title": "Discovery Phase",
        "body": "List all external dependencies (files, commands, services)\n Document what each dependency provides\n Identify which parts could vary between devices"
      },
      {
        "title": "Implementation Phase",
        "body": "Make variations configurable (with sensible defaults)\n Add validation for each input\n Build fallback chains for common variations\n Add --dry-run or --test mode"
      },
      {
        "title": "Testing Phase",
        "body": "Test with correct config → Should work\n Test with wrong config → Should fallback or fail gracefully\n Test with missing data → Should give helpful error\n Test with multiple entries → Should handle ambiguity"
      },
      {
        "title": "Documentation Phase",
        "body": "Document default assumptions\n Document how to verify local setup\n Document common variations and how to handle them\n Include data flow diagram\n Add troubleshooting section"
      },
      {
        "title": "Original (Broken)",
        "body": "# Assumes single entry, no validation, no fallback\nKEYCHAIN_DATA=$(security find-generic-password -s \"Service\" -w)\nREFRESH_TOKEN=$(echo \"$KEYCHAIN_DATA\" | jq -r '.refreshToken')\n# Use token (hope it's valid)\n\nProblems:\n\nReturns first alphabetical match (wrong entry)\nNo validation (could be empty/malformed)\nNo fallback (fails if account name differs)"
      },
      {
        "title": "Fixed (Portable)",
        "body": "# Explicit account with validation and fallback\nvalidate_data() {\n    echo \"$1\" | jq -e '.claudeAiOauth.refreshToken' > /dev/null 2>&1\n}\n\n# Try configured account\nDATA=$(security find-generic-password -s \"$SERVICE\" -a \"$ACCOUNT\" -w 2>&1)\nif validate_data \"$DATA\"; then\n    log \"✓ Using account: $ACCOUNT\"\nelse\n    log \"⚠ Trying fallback accounts...\"\n    for fallback in \"claude\" \"Claude Code\" \"default\"; do\n        DATA=$(security find-generic-password -s \"$SERVICE\" -a \"$fallback\" -w 2>&1)\n        if validate_data \"$DATA\"; then\n            ACCOUNT=\"$fallback\"\n            log \"✓ Found data in: $fallback\"\n            break\n        fi\n    done\nfi\n\n[[ -z \"$DATA\" ]] || ! validate_data \"$DATA\" && error \"No valid data found\nTried accounts: $ACCOUNT, claude, Claude Code, default\nVerify with: security find-generic-password -l '$SERVICE'\"\n\nREFRESH_TOKEN=$(echo \"$DATA\" | jq -r '.claudeAiOauth.refreshToken')\n\nImprovements:\n\n✅ Explicit account parameter\n✅ Validates data structure\n✅ Automatic fallback to common names\n✅ Helpful error with verification command"
      },
      {
        "title": "Anti-Pattern 1: \"Works On My Machine\"",
        "body": "FILE=\"/Users/patrick/.config/app.json\"  # Hardcoded path\n\nFix: Use $HOME, detect OS, or make configurable"
      },
      {
        "title": "Anti-Pattern 2: \"Hope It's There\"",
        "body": "TOKEN=$(cat config.json | jq -r '.token')\n# What if .token doesn't exist? Script continues with empty value\n\nFix: Validate before using\n\nTOKEN=$(cat config.json | jq -r '.token // empty')\n[[ -z \"$TOKEN\" ]] && error \"No token in config\""
      },
      {
        "title": "Anti-Pattern 3: \"First Match Is Right\"",
        "body": "# If multiple entries exist, which one?\nENTRY=$(find_entry \"service\")\n\nFix: Be explicit or enumerate all\n\nENTRY=$(find_entry \"service\" \"account\")  # Specific\n# OR\nALL=$(find_all_entries \"service\")\nfor entry in $ALL; do\n    validate_and_use \"$entry\"\ndone"
      },
      {
        "title": "Anti-Pattern 4: \"Silent Failures\"",
        "body": "process_data || true  # Ignore errors\n\nFix: Fail loudly with context\n\nprocess_data || error \"Failed to process\nData: $DATA\nExpected: { ... }\nCheck: command_to_verify\""
      },
      {
        "title": "With sprint-plan.md",
        "body": "Add to testing section:\n\n## Cross-Device Testing\n- [ ] Test with different account names\n- [ ] Test with wrong config values\n- [ ] Test with missing data\n- [ ] Document fallback behavior"
      },
      {
        "title": "With PRIVACY-CHECKLIST.md",
        "body": "Add before publishing:\n\n## Portability Check\n- [ ] No hardcoded paths (use $HOME, detect OS)\n- [ ] No hardcoded names (use config or fallback)\n- [ ] Validation on all inputs\n- [ ] Helpful errors for common issues"
      },
      {
        "title": "With skill-creator",
        "body": "When building new skills:\n\nList what varies between devices\nMake it configurable or auto-discoverable\nTest with wrong config\nDocument troubleshooting"
      },
      {
        "title": "Quick Reference Card",
        "body": "Before writing code:\n\nWhat varies between devices?\nHow do I prove this works?\nWhat happens when it breaks?\n\nMandatory patterns:\n\nExplicit over implicit\nValidate before use\nFallback chains\nHelpful errors\n\nTesting:\n\nCorrect config → Works\nWrong config → Fallback or helpful error\nMissing data → Clear diagnostic\n\nDocumentation:\n\nData flow diagram\nCommon variations\nTroubleshooting guide"
      },
      {
        "title": "Success Criteria",
        "body": "A tool is portable when:\n\n✅ Works on different devices without modification\n✅ Auto-discovers common variations in setup\n✅ Fails gracefully with actionable error messages\n✅ Can be debugged by reading the error output\n✅ Documentation covers \"what if my setup differs\"\n\nTest: Give it to someone with a different setup. If they need to ask you questions, the tool isn't portable yet."
      },
      {
        "title": "Origin Story",
        "body": "This methodology emerged from debugging the OAuth refresher (2026-01-23):\n\nScript read wrong keychain entry (didn't specify account)\nAssumed single entry existed (multiple did)\nNo validation (used empty data)\nNo fallback (failed on different account names)\n\nPatrick's approach:\n\nAsked for exact data (how many entries, which has tokens)\nDemanded proof (show BEFORE/AFTER tokens)\nThought cross-device (what if naming differs?)\n\nResult: Tool went from single-device/broken to universal/production-ready.\n\nKey insight: The bugs weren't in the logic - they were in the assumptions."
      },
      {
        "title": "When To Use This Skill",
        "body": "Use when:\n\nBuilding tools that read system configuration\nWorking with keychains, credentials, environment variables\nCreating scripts that run on multiple machines\nPublishing skills to ClawdHub (others will use them)\n\nApply:\n\nBefore implementing: Answer the three questions\nDuring implementation: Use mandatory patterns\nBefore testing: Run pre-flight checklist\nAfter testing: Document variations and troubleshooting\n\nRemember: Your device is just one case. Build for the general case."
      }
    ],
    "body": "Portable Tools - Cross-Device Development Methodology\n\nMethodology for building tools that work across different devices, naming schemes, and configurations. Based on lessons from OAuth refresher debugging session (2026-01-23).\n\nCore Principle\n\nNever assume your device is the only device.\n\nYour local setup is just one of many possible configurations. Build for the general case, not the specific instance.\n\nThe Three Questions (Before Writing Code)\n1. \"What varies between devices?\"\n\nBefore writing any code that reads configuration, data, or credentials:\n\nAsk:\n\nFile paths? (macOS vs Linux, different home dirs)\nAccount names? (user123 vs default vs oauth)\nService names? (slight variations in spelling/capitalization)\nData structure? (different versions, different formats)\nEnvironment? (different shells, different tools available)\n\nExample from OAuth refresher:\n\n❌ Assumed: Account is always \"claude\"\n✅ Reality: Could be \"claude\", \"Claude Code\", \"default\", etc.\n\nAction: List variables, make them configurable or auto-discoverable\n\n2. \"How do I prove this works?\"\n\nBefore claiming success:\n\nRequire:\n\nConcrete BEFORE state (exact values)\nConcrete AFTER state (exact values)\nProof they're different (side-by-side comparison)\n\nExample from OAuth refresher:\n\nBEFORE:\n- Access Token: POp5z1fi...eSN9VAAA\n- Expires: 1769189639000\n\nAFTER:\n- Access Token: 01v0RrFG...eOE9QAA ✅ Different\n- Expires: 1769190268000 ✅ Extended\n\n\nAction: Always show data transformation with real values\n\n3. \"What happens when it breaks?\"\n\nBefore pushing to production:\n\nTest:\n\nWrong configuration (intentionally break config)\nMissing data (remove expected fields)\nMultiple entries (ambiguous case)\nEdge cases (empty values, special characters)\n\nExample from OAuth refresher:\n\nTest with keychain_account: \"wrong-name\" → Fallback should work\nTest with incomplete keychain data → Should fail gracefully with helpful error\n\nAction: Test failure modes, not just happy path\n\nMandatory Patterns\nPattern 1: Explicit Over Implicit\n\n❌ Wrong:\n\n# Ambiguous - returns first match\nsecurity find-generic-password -s \"Service\" -w\n\n\n✅ Correct:\n\n# Explicit - returns specific entry\nsecurity find-generic-password -s \"Service\" -a \"account\" -w\n\n\nRule: If a command can be ambiguous, make it explicit.\n\nPattern 2: Validate Before Use\n\n❌ Wrong:\n\nDATA=$(read_config)\nUSE_VALUE=\"$DATA\"  # Hope it's valid\n\n\n✅ Correct:\n\nDATA=$(read_config)\nif ! validate_structure \"$DATA\"; then\n    error \"Invalid data structure\"\nfi\nUSE_VALUE=\"$DATA\"\n\n\nRule: Never assume data has expected structure.\n\nPattern 3: Fallback Chains\n\n❌ Wrong:\n\nACCOUNT=\"claude\"  # Hardcoded\n\n\n✅ Correct:\n\n# Try configured → Try common → Error with help\nACCOUNT=\"${CONFIG_ACCOUNT}\"\nif ! has_data \"$ACCOUNT\"; then\n    for fallback in \"claude\" \"default\" \"oauth\"; do\n        if has_data \"$fallback\"; then\n            ACCOUNT=\"$fallback\"\n            break\n        fi\n    done\nfi\n[[ -z \"$ACCOUNT\" ]] && error \"No account found. Tried: ...\"\n\n\nRule: Provide automatic fallbacks for common variations.\n\nPattern 4: Helpful Errors\n\n❌ Wrong:\n\n[[ -z \"$TOKEN\" ]] && error \"No token\"\n\n\n✅ Correct:\n\n[[ -z \"$TOKEN\" ]] && error \"No token found\n\nChecked:\n- Config: $CONFIG_FILE\n- Field: $FIELD_NAME\n- Expected: { \\\"tokens\\\": { \\\"refresh\\\": \\\"...\\\" } }\n\nVerify with:\n  cat $CONFIG_FILE | jq '.tokens'\n\"\n\n\nRule: Error messages should help user diagnose and fix.\n\nDebugging Methodology (Patrick's Approach)\nStep 1: Get Exact Data\n\nDon't ask: \"Is it broken?\"\nAsk: \"What exact values do you see? How many entries exist? Which one has the data?\"\n\nExample:\n\n# Vague\n\"Check keychain\"\n\n# Specific\n\"Run: security find-generic-password -l 'Service' | grep 'acct'\"\n\"Tell me: 1. How many entries 2. Which has tokens 3. Last modified\"\n\nStep 2: Prove With Concrete Examples\n\nDon't say: \"It should work now\"\nShow: \"Here's the BEFORE token (POp5z...), here's AFTER (01v0R...), they're different\"\n\nTemplate:\n\nBEFORE:\n- Field1: <exact_value>\n- Field2: <exact_value>\n\nAFTER:\n- Field1: <new_value> ✅ Changed\n- Field2: <new_value> ✅ Changed\n\nPROOF: Values are different\n\nStep 3: Think Cross-Device Immediately\n\nDon't think: \"Works on my machine\"\nThink: \"What if their setup differs in [X]?\"\n\nChecklist:\n\n Different account names?\n Different file paths?\n Different tools/versions?\n Different permissions?\n Different data formats?\nPre-Flight Checklist (Before Publishing)\nDiscovery Phase\n List all external dependencies (files, commands, services)\n Document what each dependency provides\n Identify which parts could vary between devices\nImplementation Phase\n Make variations configurable (with sensible defaults)\n Add validation for each input\n Build fallback chains for common variations\n Add --dry-run or --test mode\nTesting Phase\n Test with correct config → Should work\n Test with wrong config → Should fallback or fail gracefully\n Test with missing data → Should give helpful error\n Test with multiple entries → Should handle ambiguity\nDocumentation Phase\n Document default assumptions\n Document how to verify local setup\n Document common variations and how to handle them\n Include data flow diagram\n Add troubleshooting section\nReal-World Example: OAuth Refresher\nOriginal (Broken)\n# Assumes single entry, no validation, no fallback\nKEYCHAIN_DATA=$(security find-generic-password -s \"Service\" -w)\nREFRESH_TOKEN=$(echo \"$KEYCHAIN_DATA\" | jq -r '.refreshToken')\n# Use token (hope it's valid)\n\n\nProblems:\n\nReturns first alphabetical match (wrong entry)\nNo validation (could be empty/malformed)\nNo fallback (fails if account name differs)\nFixed (Portable)\n# Explicit account with validation and fallback\nvalidate_data() {\n    echo \"$1\" | jq -e '.claudeAiOauth.refreshToken' > /dev/null 2>&1\n}\n\n# Try configured account\nDATA=$(security find-generic-password -s \"$SERVICE\" -a \"$ACCOUNT\" -w 2>&1)\nif validate_data \"$DATA\"; then\n    log \"✓ Using account: $ACCOUNT\"\nelse\n    log \"⚠ Trying fallback accounts...\"\n    for fallback in \"claude\" \"Claude Code\" \"default\"; do\n        DATA=$(security find-generic-password -s \"$SERVICE\" -a \"$fallback\" -w 2>&1)\n        if validate_data \"$DATA\"; then\n            ACCOUNT=\"$fallback\"\n            log \"✓ Found data in: $fallback\"\n            break\n        fi\n    done\nfi\n\n[[ -z \"$DATA\" ]] || ! validate_data \"$DATA\" && error \"No valid data found\nTried accounts: $ACCOUNT, claude, Claude Code, default\nVerify with: security find-generic-password -l '$SERVICE'\"\n\nREFRESH_TOKEN=$(echo \"$DATA\" | jq -r '.claudeAiOauth.refreshToken')\n\n\nImprovements:\n\n✅ Explicit account parameter\n✅ Validates data structure\n✅ Automatic fallback to common names\n✅ Helpful error with verification command\nCommon Anti-Patterns\nAnti-Pattern 1: \"Works On My Machine\"\nFILE=\"/Users/patrick/.config/app.json\"  # Hardcoded path\n\n\nFix: Use $HOME, detect OS, or make configurable\n\nAnti-Pattern 2: \"Hope It's There\"\nTOKEN=$(cat config.json | jq -r '.token')\n# What if .token doesn't exist? Script continues with empty value\n\n\nFix: Validate before using\n\nTOKEN=$(cat config.json | jq -r '.token // empty')\n[[ -z \"$TOKEN\" ]] && error \"No token in config\"\n\nAnti-Pattern 3: \"First Match Is Right\"\n# If multiple entries exist, which one?\nENTRY=$(find_entry \"service\")\n\n\nFix: Be explicit or enumerate all\n\nENTRY=$(find_entry \"service\" \"account\")  # Specific\n# OR\nALL=$(find_all_entries \"service\")\nfor entry in $ALL; do\n    validate_and_use \"$entry\"\ndone\n\nAnti-Pattern 4: \"Silent Failures\"\nprocess_data || true  # Ignore errors\n\n\nFix: Fail loudly with context\n\nprocess_data || error \"Failed to process\nData: $DATA\nExpected: { ... }\nCheck: command_to_verify\"\n\nIntegration With Existing Workflows\nWith sprint-plan.md\n\nAdd to testing section:\n\n## Cross-Device Testing\n- [ ] Test with different account names\n- [ ] Test with wrong config values\n- [ ] Test with missing data\n- [ ] Document fallback behavior\n\nWith PRIVACY-CHECKLIST.md\n\nAdd before publishing:\n\n## Portability Check\n- [ ] No hardcoded paths (use $HOME, detect OS)\n- [ ] No hardcoded names (use config or fallback)\n- [ ] Validation on all inputs\n- [ ] Helpful errors for common issues\n\nWith skill-creator\n\nWhen building new skills:\n\nList what varies between devices\nMake it configurable or auto-discoverable\nTest with wrong config\nDocument troubleshooting\nQuick Reference Card\n\nBefore writing code:\n\nWhat varies between devices?\nHow do I prove this works?\nWhat happens when it breaks?\n\nMandatory patterns:\n\nExplicit over implicit\nValidate before use\nFallback chains\nHelpful errors\n\nTesting:\n\nCorrect config → Works\nWrong config → Fallback or helpful error\nMissing data → Clear diagnostic\n\nDocumentation:\n\nData flow diagram\nCommon variations\nTroubleshooting guide\nSuccess Criteria\n\nA tool is portable when:\n\n✅ Works on different devices without modification\n✅ Auto-discovers common variations in setup\n✅ Fails gracefully with actionable error messages\n✅ Can be debugged by reading the error output\n✅ Documentation covers \"what if my setup differs\"\n\nTest: Give it to someone with a different setup. If they need to ask you questions, the tool isn't portable yet.\n\nOrigin Story\n\nThis methodology emerged from debugging the OAuth refresher (2026-01-23):\n\nScript read wrong keychain entry (didn't specify account)\nAssumed single entry existed (multiple did)\nNo validation (used empty data)\nNo fallback (failed on different account names)\n\nPatrick's approach:\n\nAsked for exact data (how many entries, which has tokens)\nDemanded proof (show BEFORE/AFTER tokens)\nThought cross-device (what if naming differs?)\n\nResult: Tool went from single-device/broken to universal/production-ready.\n\nKey insight: The bugs weren't in the logic - they were in the assumptions.\n\nWhen To Use This Skill\n\nUse when:\n\nBuilding tools that read system configuration\nWorking with keychains, credentials, environment variables\nCreating scripts that run on multiple machines\nPublishing skills to ClawdHub (others will use them)\n\nApply:\n\nBefore implementing: Answer the three questions\nDuring implementation: Use mandatory patterns\nBefore testing: Run pre-flight checklist\nAfter testing: Document variations and troubleshooting\n\nRemember: Your device is just one case. Build for the general case."
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/TunaIssaCoding/portable-tools",
    "publisherUrl": "https://clawhub.ai/TunaIssaCoding/portable-tools",
    "owner": "TunaIssaCoding",
    "version": "1.2.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/portable-tools",
    "downloadUrl": "https://openagent3.xyz/downloads/portable-tools",
    "agentUrl": "https://openagent3.xyz/skills/portable-tools/agent",
    "manifestUrl": "https://openagent3.xyz/skills/portable-tools/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/portable-tools/agent.md"
  }
}