{
  "schemaVersion": "1.0",
  "item": {
    "slug": "openclaw-credential-manager",
    "name": "OpenClaw Credential Manager",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/teeclaw/openclaw-credential-manager",
    "canonicalUrl": "https://clawhub.ai/teeclaw/openclaw-credential-manager",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/openclaw-credential-manager",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=openclaw-credential-manager",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "CHANGELOG.md",
      "CONSOLIDATION-RULE.md",
      "CORE-PRINCIPLE.md",
      "README.md",
      "SKILL.md",
      "references/security.md"
    ],
    "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/openclaw-credential-manager"
    },
    "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/openclaw-credential-manager",
    "agentPageUrl": "https://openagent3.xyz/skills/openclaw-credential-manager/agent",
    "manifestUrl": "https://openagent3.xyz/skills/openclaw-credential-manager/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/openclaw-credential-manager/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": "Credential Manager",
        "body": "STATUS: MANDATORY SECURITY FOUNDATION\n\nConsolidate scattered API keys and credentials into a secure, centralized .env file."
      },
      {
        "title": "⚠️ This Is Not Optional",
        "body": "Centralized .env credential management is a core requirement for OpenClaw security. If your credentials are scattered across multiple files, stop and consolidate them now.\n\nTHE RULE: All credentials MUST be in ~/.openclaw/.env ONLY. No workspace, no skills, no scripts directories.\n\nSee:\n\nCORE-PRINCIPLE.md - Why this is non-negotiable\nCONSOLIDATION-RULE.md - The single source principle"
      },
      {
        "title": "The Foundation",
        "body": "Every OpenClaw deployment MUST have:\n\n~/.openclaw/.env (mode 600)\n\nThis is your single source of truth for all credentials. No exceptions.\n\nWhy?\n\nSingle location = easier to secure\nFile mode 600 = only you can read\nGit-ignored = won't accidentally commit\nValidated format = catches errors\nAudit trail = know what changed\n\nScattered credentials = scattered attack surface. This skill fixes that."
      },
      {
        "title": "What This Skill Does",
        "body": "Scans for credentials in common locations (including deep scan for hardcoded secrets)\nBacks up existing credential files (timestamped, mode 600)\nConsolidates into ~/.openclaw/.env\nSecures with proper permissions (600 files, 700 directories)\nValidates security, format, and entropy\nEncrypts high-value secrets with GPG (wallet keys, private keys, mnemonics)\nTracks credential rotation schedules\nEnforces best practices via fail-fast checks\nCleans up old files after migration"
      },
      {
        "title": "Detection Parameters",
        "body": "The skill automatically detects credentials by scanning for:\n\nFile Patterns:\n\n~/.config/*/credentials.json — Service config directories\n~/.config/*/*.credentials.json — Nested credential files\n~/.openclaw/*.json — Credential files in OpenClaw root\n~/.openclaw/*-credentials* — Named credential files (e.g., farcaster-credentials.json)\n~/.openclaw/workspace/memory/*-creds.json — Memory credential files\n~/.openclaw/workspace/memory/*credentials*.json — Memory credential files\n~/.openclaw/workspace/.env — Workspace env files\n~/.openclaw/workspace/*/.env — Subdirectory env files\n~/.openclaw/workspace/skills/*/.env — Skill env files\n~/.local/share/*/credentials.json — Local share directories\n\nSensitive Key Patterns:\n\nAPI keys, access tokens, bearer tokens\nSecrets, passwords, passphrases\nOAuth consumer keys\nPrivate keys, signing keys, wallet keys\nMnemonics and seed phrases\n\nDeep Scan (--deep flag):\n\nGreps .sh, .js, .py, .mjs, .ts files for hardcoded secrets\nDetects high-entropy strings matching common key prefixes (sk_, pk_, Bearer, 0x + 64 hex)\nExcludes node_modules/, .git/\nReports file, line number, and key pattern matched\n\nSecurity Checks:\n\nFile permissions (must be 600 for files, 700 for directories)\nBackup permissions (must be 600 for backup files, 700 for backup dirs)\nGit-ignore protection\nFormat validation (allows quoted values with spaces)\nEntropy analysis (flags suspiciously low-entropy secrets)\nPrivate key detection (flags 0x + 64 hex char values)\nMnemonic detection (flags 12/24 word values)\nSymlink detection (validates symlinked .env targets)"
      },
      {
        "title": "Full Migration (Recommended)",
        "body": "# Scan for credentials\n./scripts/scan.py\n\n# Deep scan (includes hardcoded secrets in scripts)\n./scripts/scan.py --deep\n\n# Review and consolidate\n./scripts/consolidate.py\n\n# Validate security\n./scripts/validate.py\n\n# Encrypt high-value secrets\n./scripts/encrypt.py --keys MAIN_WALLET_PRIVATE_KEY,CUSTODY_PRIVATE_KEY\n\n# Check rotation status\n./scripts/rotation-check.py"
      },
      {
        "title": "Individual Operations",
        "body": "# Scan only\n./scripts/scan.py\n\n# Consolidate specific service\n./scripts/consolidate.py --service x\n\n# Backup without removing\n./scripts/consolidate.py --backup-only\n\n# Clean up old files\n./scripts/cleanup.py --confirm"
      },
      {
        "title": "Common Credential Locations",
        "body": "The skill scans these locations:\n\n~/.config/*/credentials.json\n~/.openclaw/*.json\n~/.openclaw/*-credentials*\n~/.openclaw/workspace/memory/*-creds.json\n~/.openclaw/workspace/memory/*credentials*.json\n~/.openclaw/workspace/*/.env\n~/.openclaw/workspace/skills/*/.env\n~/.env (if exists, merges)"
      },
      {
        "title": "Security Features",
        "body": "✅ File permissions: Sets .env to mode 600 (owner only)\n✅ Directory permissions: Sets backup dirs to mode 700 (owner only)\n✅ Backup permissions: Sets backup files to mode 600 (owner only)\n✅ Git protection: Creates/updates .gitignore\n✅ Backups: Timestamped backups before changes (secured)\n✅ Validation: Checks format, permissions, entropy, and duplicates\n✅ Template: Creates .env.example (safe to share)\n✅ GPG encryption: Encrypts high-value secrets at rest\n✅ Rotation tracking: Warns when credentials need rotation\n✅ Deep scan: Detects hardcoded secrets in source files\n✅ Symlink-aware: Validates symlinked .env targets"
      },
      {
        "title": "Output Structure",
        "body": "After migration:\n\n~/.openclaw/\n├── .env                     # All credentials (secure, mode 600)\n├── .env.secrets.gpg         # GPG-encrypted high-value keys (mode 600)\n├── .env.meta                # Rotation metadata (mode 600)\n├── .env.example             # Template (safe to share)\n├── .gitignore               # Protects .env and .env.secrets.gpg\n└── backups/                 # (mode 700)\n    └── credentials-old-YYYYMMDD/  # (mode 700)\n        └── *.bak            # Backup files (mode 600)"
      },
      {
        "title": "GPG Encryption for High-Value Secrets",
        "body": "Private keys, wallet keys, and mnemonics should never exist as plaintext on disk. Use GPG encryption for these."
      },
      {
        "title": "Setup GPG",
        "body": "# First-time setup (generates OpenClaw GPG key, configures agent cache)\n./scripts/setup-gpg.sh"
      },
      {
        "title": "Encrypt High-Value Keys",
        "body": "# Encrypt specific keys (moves them from .env to .env.secrets.gpg)\n./scripts/encrypt.py --keys MAIN_WALLET_PRIVATE_KEY,CUSTODY_PRIVATE_KEY,SIGNER_PRIVATE_KEY\n\n# The .env will contain placeholders:\n# MAIN_WALLET_PRIVATE_KEY=GPG:MAIN_WALLET_PRIVATE_KEY"
      },
      {
        "title": "How Scripts Access Encrypted Keys",
        "body": "The enforce.py module handles this transparently:\n\nfrom enforce import get_credential\n\n# Works for both plaintext and GPG-encrypted keys\nkey = get_credential('MAIN_WALLET_PRIVATE_KEY')\n# If value starts with \"GPG:\", decrypts from .env.secrets.gpg automatically"
      },
      {
        "title": "GPG Agent Caching",
        "body": "On headless servers (VPS), the GPG agent caches the passphrase:\n\nDefault cache TTL: 8 hours\nConfigurable via setup-gpg.sh\nPassphrase required once after reboot, then cached"
      },
      {
        "title": "What to Encrypt",
        "body": "Key TypeEncrypt?WhyWallet private keys✅ YesControls fundsCustody/signer private keys✅ YesControls identityMnemonics / seed phrases✅ YesMaster recoveryAPI keys (services)❌ NoRevocable, low damageAgent IDs, names, URLs❌ NoNot secrets"
      },
      {
        "title": "Setup Rotation Metadata",
        "body": "# Initialize rotation tracking for all keys\n./scripts/rotation-check.py --init\n\nCreates ~/.openclaw/.env.meta:\n\n{\n  \"MAIN_WALLET_PRIVATE_KEY\": {\n    \"created\": \"2026-01-15\",\n    \"lastRotated\": null,\n    \"rotationDays\": 90,\n    \"risk\": \"critical\"\n  },\n  \"MOLTBOOK_API_KEY\": {\n    \"created\": \"2026-02-04\",\n    \"lastRotated\": null,\n    \"rotationDays\": 180,\n    \"risk\": \"low\"\n  }\n}"
      },
      {
        "title": "Check Rotation Status",
        "body": "# Check which keys need rotation\n./scripts/rotation-check.py\n\n# Output:\n# 🔴 MAIN_WALLET_PRIVATE_KEY: 26 days old (critical, rotate every 90 days)\n# ✅ MOLTBOOK_API_KEY: 7 days old (low, rotate every 180 days)"
      },
      {
        "title": "Rotation Schedules",
        "body": "Risk LevelRotation PeriodExamplesCritical90 daysWallet keys, private keysStandard180 daysAPI keys for paid servicesLow365 daysFree-tier API keys, agent IDs"
      },
      {
        "title": "Add to Heartbeat (Optional)",
        "body": "Add rotation checks to HEARTBEAT.md for periodic monitoring:\n\n## Credential Rotation (weekly)\nIf 7+ days since last rotation check:\n1. Run: ./scripts/rotation-check.py\n2. If any keys overdue: notify human\n3. Update lastRotationCheck timestamp"
      },
      {
        "title": "Supported Services",
        "body": "Common services auto-detected:\n\nX (Twitter): OAuth 1.0a credentials\nFarcaster: Custody keys, signer keys, FID credentials\nMolten: Agent intent matching\nMoltbook: Agent social network\nBotchan/4claw: Net Protocol\nOpenAI, Anthropic, Google: AI providers\nGitHub, GitLab: Code hosting\nCoinbase/CDP: Crypto wallet credentials\nGeneric: API_KEY, *_TOKEN, *_SECRET patterns\n\nSee references/supported-services.md for full list."
      },
      {
        "title": "Scripts",
        "body": "All scripts support --help for detailed usage."
      },
      {
        "title": "scan.py",
        "body": "# Scan and report\n./scripts/scan.py\n\n# Deep scan (includes hardcoded secrets in scripts)\n./scripts/scan.py --deep\n\n# Include custom paths\n./scripts/scan.py --paths ~/.myapp/config ~/.local/share/creds\n\n# JSON output\n./scripts/scan.py --format json"
      },
      {
        "title": "consolidate.py",
        "body": "# Interactive mode (prompts before changes)\n./scripts/consolidate.py\n\n# Auto-confirm (no prompts)\n./scripts/consolidate.py --yes\n\n# Backup only\n./scripts/consolidate.py --backup-only\n\n# Specific service\n./scripts/consolidate.py --service molten"
      },
      {
        "title": "validate.py",
        "body": "# Full validation (permissions, format, entropy, security)\n./scripts/validate.py\n\n# Check permissions only\n./scripts/validate.py --check permissions\n\n# Fix issues automatically\n./scripts/validate.py --fix"
      },
      {
        "title": "encrypt.py",
        "body": "# Encrypt specific high-value keys\n./scripts/encrypt.py --keys MAIN_WALLET_PRIVATE_KEY,CUSTODY_PRIVATE_KEY\n\n# List currently encrypted keys\n./scripts/encrypt.py --list\n\n# Decrypt (move back to plaintext .env)\n./scripts/encrypt.py --decrypt --keys MAIN_WALLET_PRIVATE_KEY"
      },
      {
        "title": "rotation-check.py",
        "body": "# Check rotation status\n./scripts/rotation-check.py\n\n# Initialize tracking for all keys\n./scripts/rotation-check.py --init\n\n# Record a rotation\n./scripts/rotation-check.py --rotated MOLTBOOK_API_KEY"
      },
      {
        "title": "setup-gpg.sh",
        "body": "# First-time GPG setup for OpenClaw\n./scripts/setup-gpg.sh\n\n# Configure cache timeout (hours)\n./scripts/setup-gpg.sh --cache-hours 12"
      },
      {
        "title": "cleanup.py",
        "body": "# Dry run (shows what would be deleted)\n./scripts/cleanup.py\n\n# Actually delete old files\n./scripts/cleanup.py --confirm\n\n# Keep backups\n./scripts/cleanup.py --confirm --keep-backups"
      },
      {
        "title": "Migration Workflow",
        "body": "This is the exact step-by-step flow, tested and verified on a live OpenClaw deployment."
      },
      {
        "title": "Step 1: Scan for Scattered Credentials",
        "body": "cd /path/to/openclaw/skills/credential-manager\n\n# Basic scan — finds credential files by path patterns\n./scripts/scan.py\n\n# Deep scan — also greps source files for hardcoded secrets\n./scripts/scan.py --deep\n\nWhat to look for in output:\n\n⚠️ files with mode != 600 (insecure permissions)\nSymlinked .env files (should point to main ~/.openclaw/.env)\nJSON credential files outside ~/.openclaw/.env\nDeep scan hits on hardcoded keys in scripts\n\nExample output:\n\n⚠️ /home/user/.openclaw/farcaster-credentials.json\n   Type: json\n   Keys: custodyPrivateKey, signerPrivateKey, ...\n   Mode: 644\n   ⚠️  Should be 600 for security\n\n✅ /home/user/.openclaw/.env\n   Type: env\n   Keys: API_KEY, X_CONSUMER_KEY, ...\n   Mode: 600"
      },
      {
        "title": "Step 2: Consolidate into .env",
        "body": "./scripts/consolidate.py\n\nInteractive flow:\n\nScript scans and lists all credential files found\nBacks up existing .env to ~/.openclaw/backups/credentials-old-YYYYMMDD/\nLoads existing .env keys\nProcesses each credential file:\n\nAuto-detects service (x, farcaster, moltbook, molten, etc.)\nNormalizes key names (e.g., custodyPrivateKey → FARCASTER_CUSTODY_PRIVATE_KEY)\nShows mapping: key → ENV_KEY\n\n\nAsks for confirmation: Proceed? [y/N]\nWrites merged .env (mode 600)\nCreates .env.example template (safe to share)\nUpdates .gitignore\n\nFor credentials not auto-detected (e.g., nested JSON like farcaster-credentials.json with multiple accounts), manually add to .env:\n\ncat >> ~/.openclaw/.env << 'EOF'\n\n# FARCASTER (Active: mr-teeclaw, FID 2700953)\nFARCASTER_FID=2700953\nFARCASTER_FNAME=mr-teeclaw\nFARCASTER_CUSTODY_ADDRESS=0x...\nFARCASTER_CUSTODY_PRIVATE_KEY=0x...\nFARCASTER_SIGNER_PUBLIC_KEY=...\nFARCASTER_SIGNER_PRIVATE_KEY=...\n\n# FARCASTER LEGACY (teeclaw, FID 2684290)\nFARCASTER_LEGACY_FID=2684290\nFARCASTER_LEGACY_CUSTODY_ADDRESS=0x...\nFARCASTER_LEGACY_CUSTODY_PRIVATE_KEY=0x...\nFARCASTER_LEGACY_SIGNER_PUBLIC_KEY=...\nFARCASTER_LEGACY_SIGNER_PRIVATE_KEY=...\nEOF\n\nchmod 600 ~/.openclaw/.env"
      },
      {
        "title": "Step 3: Validate",
        "body": "./scripts/validate.py\n\nChecks performed:\n\n✅ .env permissions (must be 600)\n✅ .gitignore coverage\n✅ Format validation (key format, quoting, duplicates)\n✅ Security analysis:\n\nDetects plaintext private keys (0x + 64 hex chars) → recommends GPG\nDetects mnemonic/seed phrases (12/24 word values) → recommends GPG\nEntropy analysis on SECRET/PRIVATE_KEY/PASSWORD fields\nFlags weak/placeholder values\n\n\n✅ Backup permissions (files must be 600, directories 700)\n\nFix issues automatically:\n\n./scripts/validate.py --fix\n\nThis fixes: file permissions, directory permissions, backup permissions, gitignore.\nIt does NOT auto-fix format issues or encrypt keys — those require manual action."
      },
      {
        "title": "Step 4: Setup GPG and Encrypt Private Keys",
        "body": "# First-time GPG setup (configures agent cache, tests encrypt/decrypt)\n./scripts/setup-gpg.sh\n# Optional: --cache-hours 12 (default: 8)\n\nEncrypt high-value keys:\n\n# Encrypt wallet + Farcaster private keys\n./scripts/encrypt.py --keys MAIN_WALLET_PRIVATE_KEY,FARCASTER_CUSTODY_PRIVATE_KEY,FARCASTER_SIGNER_PRIVATE_KEY,FARCASTER_LEGACY_CUSTODY_PRIVATE_KEY,FARCASTER_LEGACY_SIGNER_PRIVATE_KEY\n\nWhat happens:\n\nPrompts for a GPG passphrase (or reads OPENCLAW_GPG_PASSPHRASE env var)\nExtracts specified key values from .env\nStores them encrypted in ~/.openclaw/.env.secrets.gpg (AES256, mode 600)\nReplaces .env values with GPG:KEY_NAME placeholders\nScripts using get_credential() or _load_cred() decrypt transparently\n\nSave passphrase to .env for automated decryption:\n\necho 'OPENCLAW_GPG_PASSPHRASE=your-passphrase-here' >> ~/.openclaw/.env\nchmod 600 ~/.openclaw/.env\n\nVerify encryption:\n\n# Check .env has GPG placeholders\ngrep \"GPG:\" ~/.openclaw/.env\n\n# List all encrypted keys\n./scripts/encrypt.py --list"
      },
      {
        "title": "Step 5: Initialize Rotation Tracking",
        "body": "./scripts/rotation-check.py --init\n\nAuto-classifies all keys by risk:\n\nCritical (90-day rotation): *PRIVATE_KEY, *MNEMONIC, *SEED, *WALLET_KEY, *CUSTODY*, *SIGNER*\nStandard (180-day rotation): *API_KEY, *SECRET, *TOKEN, *BEARER, *CONSUMER*, *ACCESS*\nLow (365-day rotation): Everything else\n\nCreates ~/.openclaw/.env.meta (mode 600) with creation dates and rotation schedules.\n\nCheck rotation status anytime:\n\n./scripts/rotation-check.py"
      },
      {
        "title": "Step 6: Cleanup Old Credential Files",
        "body": "# Dry run first — see what would be deleted\n./scripts/cleanup.py\n\n# Actually delete (prompts for 'DELETE' confirmation)\n./scripts/cleanup.py --confirm\n\nAlso manually remove migrated files not caught by the scanner:\n\n# Example: farcaster-credentials.json was manually migrated\ncp ~/.openclaw/farcaster-credentials.json ~/.openclaw/backups/credentials-old-YYYYMMDD/farcaster-credentials.json.bak\nchmod 600 ~/.openclaw/backups/credentials-old-YYYYMMDD/farcaster-credentials.json.bak\nrm ~/.openclaw/farcaster-credentials.json"
      },
      {
        "title": "Step 7: Update Scripts That Referenced Old Files",
        "body": "Any scripts that loaded from JSON credential files or hardcoded paths need updating.\n\nPattern — Bash scripts:\n\n# OLD (insecure):\nFARCASTER_CREDS=\"/home/user/.openclaw/farcaster-credentials.json\"\nfid=$(jq -r '.fid' \"$FARCASTER_CREDS\")\nprivate_key=$(jq -r '.custodyPrivateKey' \"$FARCASTER_CREDS\")\n\n# NEW (secure, GPG-aware):\nENV_FILE=\"$HOME/.openclaw/.env\"\n\n_load_cred() {\n  local key=\"$1\"\n  local value\n  value=$(grep \"^${key}=\" \"$ENV_FILE\" | head -1 | cut -d= -f2-)\n  if [[ \"$value\" == GPG:* ]]; then\n    local gpg_key=\"${value#GPG:}\"\n    local passphrase=\"${OPENCLAW_GPG_PASSPHRASE:-}\"\n    if [ -n \"$passphrase\" ]; then\n      value=$(echo \"$passphrase\" | gpg -d --batch --quiet --passphrase-fd 0 \"$HOME/.openclaw/.env.secrets.gpg\" | python3 -c \"import json,sys; print(json.load(sys.stdin).get('$gpg_key',''))\")\n    else\n      value=$(gpg -d --batch --quiet \"$HOME/.openclaw/.env.secrets.gpg\" | python3 -c \"import json,sys; print(json.load(sys.stdin).get('$gpg_key',''))\")\n    fi\n  fi\n  echo \"$value\"\n}\n\nfid=$(_load_cred \"FARCASTER_FID\")\nprivate_key=$(_load_cred \"FARCASTER_CUSTODY_PRIVATE_KEY\")\n\nPattern — Node.js scripts:\n\n// OLD (insecure):\nconst creds = JSON.parse(fs.readFileSync('~/.openclaw/farcaster-credentials.json'));\nconst privateKey = creds.custodyPrivateKey;\n\n// NEW (secure, GPG-aware):\nconst ENV_PATH = path.join(os.homedir(), '.openclaw/.env');\nconst SECRETS_PATH = path.join(os.homedir(), '.openclaw/.env.secrets.gpg');\n\nfunction loadCred(key) {\n  const content = fs.readFileSync(ENV_PATH, 'utf8');\n  for (const line of content.split('\\n')) {\n    if (line.startsWith(key + '=')) {\n      let value = line.slice(key.length + 1).trim();\n      if (value.startsWith('GPG:')) {\n        const { execSync } = require('child_process');\n        const passphrase = process.env.OPENCLAW_GPG_PASSPHRASE || '';\n        const cmd = passphrase\n          ? `echo \"${passphrase}\" | gpg -d --batch --quiet --passphrase-fd 0 \"${SECRETS_PATH}\"`\n          : `gpg -d --batch --quiet \"${SECRETS_PATH}\"`;\n        const secrets = JSON.parse(execSync(cmd, { encoding: 'utf8' }));\n        return secrets[value.slice(4)] || '';\n      }\n      return value;\n    }\n  }\n  return '';\n}\n\nconst privateKey = loadCred('FARCASTER_CUSTODY_PRIVATE_KEY');\n\nPattern — Python scripts:\n\n# Use the enforce module (recommended):\nimport sys\nfrom pathlib import Path\nsys.path.insert(0, str(Path.home() / 'openclaw/skills/credential-manager/scripts'))\nfrom enforce import get_credential\n\nprivate_key = get_credential('FARCASTER_CUSTODY_PRIVATE_KEY')  # Auto-decrypts GPG"
      },
      {
        "title": "Step 8: Final Validation",
        "body": "# Run full validation — should show all green\n./scripts/validate.py\n\n# Verify encrypted keys\n./scripts/encrypt.py --list\n\n# Check rotation status\n./scripts/rotation-check.py\n\n# Test a script that uses credentials\nbash /path/to/your/script.sh\n\nExpected final state:\n\n~/.openclaw/\n├── .env                     # All credentials (mode 600, private keys = GPG:*)\n├── .env.secrets.gpg         # GPG-encrypted private keys (mode 600)\n├── .env.meta                # Rotation tracking metadata (mode 600)\n├── .env.example             # Template (safe to share)\n├── .gitignore               # Protects .env, .env.secrets.gpg, .env.meta\n└── backups/                 # (mode 700)\n    └── credentials-old-YYYYMMDD/  # (mode 700)\n        └── *.bak            # Backup files (mode 600)"
      },
      {
        "title": "For Skill Developers: Enforce This Standard",
        "body": "Other OpenClaw skills MUST validate credentials are secure before using them:"
      },
      {
        "title": "Python Skills",
        "body": "#!/usr/bin/env python3\nimport sys\nfrom pathlib import Path\n\n# Add credential-manager scripts to path\nsys.path.insert(0, str(Path.home() / '.openclaw/skills/credential-manager/scripts'))\n\n# Enforce secure .env (exits if not compliant)\nfrom enforce import require_secure_env, get_credential\n\nrequire_secure_env()\n\n# Now safe to load credentials (handles GPG-encrypted keys transparently)\napi_key = get_credential('SERVICE_API_KEY')\nwallet_key = get_credential('MAIN_WALLET_PRIVATE_KEY')  # Auto-decrypts from GPG"
      },
      {
        "title": "Bash Skills",
        "body": "#!/usr/bin/env bash\nset -euo pipefail\n\n# Validate .env exists and is secure\nif ! python3 ~/.openclaw/skills/credential-manager/scripts/enforce.py; then\n    exit 1\nfi\n\n# Now safe to load\nsource ~/.openclaw/.env\n\nThis creates a fail-fast system: If credentials aren't properly secured, skills refuse to run. Users are forced to fix it."
      },
      {
        "title": "Loading Credentials",
        "body": "After migration, load from .env:"
      },
      {
        "title": "Python",
        "body": "import os\nfrom pathlib import Path\n\n# Load .env\nenv_file = Path.home() / '.openclaw' / '.env'\nwith open(env_file) as f:\n    for line in f:\n        if '=' in line and not line.strip().startswith('#'):\n            key, val = line.strip().split('=', 1)\n            os.environ[key] = val\n\n# Use credentials\napi_key = os.getenv('SERVICE_API_KEY')"
      },
      {
        "title": "Bash",
        "body": "# Load .env\nset -a\nsource ~/.openclaw/.env\nset +a\n\n# Use credentials\necho \"$SERVICE_API_KEY\""
      },
      {
        "title": "Using Existing Loaders",
        "body": "If you migrated using OpenClaw scripts:\n\nfrom load_credentials import get_credentials\ncreds = get_credentials('x')"
      },
      {
        "title": "Adding New Credentials",
        "body": "Edit ~/.openclaw/.env:\n\n# Add new service\nNEW_SERVICE_API_KEY=your_key_here\nNEW_SERVICE_SECRET=your_secret_here\n\nUpdate template too:\n\n# Edit .env.example\nNEW_SERVICE_API_KEY=your_key_here\nNEW_SERVICE_SECRET=your_secret_here\n\nIf the new credential is high-value (private key, wallet key):\n\n# Add to .env first, then encrypt\n./scripts/encrypt.py --keys NEW_SERVICE_PRIVATE_KEY"
      },
      {
        "title": "Security Best Practices",
        "body": "See references/security.md for detailed security guidelines.\n\nQuick checklist:\n\n✅ .env has 600 permissions\n✅ .env is git-ignored\n✅ Backup files have 600 permissions\n✅ Backup directories have 700 permissions\n✅ No credentials in code or logs (use --deep scan to verify)\n✅ Private keys encrypted with GPG\n✅ Rotation schedule established and tracked\n✅ Symlinked .env files point to the main .env only\n✅ No credentials in shell history (use source, not export KEY=val)"
      },
      {
        "title": "Rollback",
        "body": "If something goes wrong:\n\n# Find your backup\nls -la ~/.openclaw/backups/\n\n# Restore specific file\ncp ~/.openclaw/backups/credentials-old-YYYYMMDD/x-credentials.json.bak \\\n   ~/.config/x/credentials.json\n\n# Decrypt GPG secrets back to plaintext\n./scripts/encrypt.py --decrypt --keys MAIN_WALLET_PRIVATE_KEY"
      },
      {
        "title": "Notes",
        "body": "Non-destructive by default: Original files backed up before removal\nIdempotent: Safe to run multiple times\nExtensible: Add custom credential patterns in scripts\nSecure: Never logs full credentials, only metadata\nGPG-aware: Transparently handles encrypted and plaintext credentials\nBackup-hardened: All backups secured with proper permissions\nSymlink-aware: Detects and validates symlinked credential files"
      }
    ],
    "body": "Credential Manager\n\nSTATUS: MANDATORY SECURITY FOUNDATION\n\nConsolidate scattered API keys and credentials into a secure, centralized .env file.\n\n⚠️ This Is Not Optional\n\nCentralized .env credential management is a core requirement for OpenClaw security. If your credentials are scattered across multiple files, stop and consolidate them now.\n\nTHE RULE: All credentials MUST be in ~/.openclaw/.env ONLY. No workspace, no skills, no scripts directories.\n\nSee:\n\nCORE-PRINCIPLE.md - Why this is non-negotiable\nCONSOLIDATION-RULE.md - The single source principle\nThe Foundation\n\nEvery OpenClaw deployment MUST have:\n\n~/.openclaw/.env (mode 600)\n\n\nThis is your single source of truth for all credentials. No exceptions.\n\nWhy?\n\nSingle location = easier to secure\nFile mode 600 = only you can read\nGit-ignored = won't accidentally commit\nValidated format = catches errors\nAudit trail = know what changed\n\nScattered credentials = scattered attack surface. This skill fixes that.\n\nWhat This Skill Does\nScans for credentials in common locations (including deep scan for hardcoded secrets)\nBacks up existing credential files (timestamped, mode 600)\nConsolidates into ~/.openclaw/.env\nSecures with proper permissions (600 files, 700 directories)\nValidates security, format, and entropy\nEncrypts high-value secrets with GPG (wallet keys, private keys, mnemonics)\nTracks credential rotation schedules\nEnforces best practices via fail-fast checks\nCleans up old files after migration\nDetection Parameters\n\nThe skill automatically detects credentials by scanning for:\n\nFile Patterns:\n\n~/.config/*/credentials.json — Service config directories\n~/.config/*/*.credentials.json — Nested credential files\n~/.openclaw/*.json — Credential files in OpenClaw root\n~/.openclaw/*-credentials* — Named credential files (e.g., farcaster-credentials.json)\n~/.openclaw/workspace/memory/*-creds.json — Memory credential files\n~/.openclaw/workspace/memory/*credentials*.json — Memory credential files\n~/.openclaw/workspace/.env — Workspace env files\n~/.openclaw/workspace/*/.env — Subdirectory env files\n~/.openclaw/workspace/skills/*/.env — Skill env files\n~/.local/share/*/credentials.json — Local share directories\n\nSensitive Key Patterns:\n\nAPI keys, access tokens, bearer tokens\nSecrets, passwords, passphrases\nOAuth consumer keys\nPrivate keys, signing keys, wallet keys\nMnemonics and seed phrases\n\nDeep Scan (--deep flag):\n\nGreps .sh, .js, .py, .mjs, .ts files for hardcoded secrets\nDetects high-entropy strings matching common key prefixes (sk_, pk_, Bearer, 0x + 64 hex)\nExcludes node_modules/, .git/\nReports file, line number, and key pattern matched\n\nSecurity Checks:\n\nFile permissions (must be 600 for files, 700 for directories)\nBackup permissions (must be 600 for backup files, 700 for backup dirs)\nGit-ignore protection\nFormat validation (allows quoted values with spaces)\nEntropy analysis (flags suspiciously low-entropy secrets)\nPrivate key detection (flags 0x + 64 hex char values)\nMnemonic detection (flags 12/24 word values)\nSymlink detection (validates symlinked .env targets)\nQuick Start\nFull Migration (Recommended)\n# Scan for credentials\n./scripts/scan.py\n\n# Deep scan (includes hardcoded secrets in scripts)\n./scripts/scan.py --deep\n\n# Review and consolidate\n./scripts/consolidate.py\n\n# Validate security\n./scripts/validate.py\n\n# Encrypt high-value secrets\n./scripts/encrypt.py --keys MAIN_WALLET_PRIVATE_KEY,CUSTODY_PRIVATE_KEY\n\n# Check rotation status\n./scripts/rotation-check.py\n\nIndividual Operations\n# Scan only\n./scripts/scan.py\n\n# Consolidate specific service\n./scripts/consolidate.py --service x\n\n# Backup without removing\n./scripts/consolidate.py --backup-only\n\n# Clean up old files\n./scripts/cleanup.py --confirm\n\nCommon Credential Locations\n\nThe skill scans these locations:\n\n~/.config/*/credentials.json\n~/.openclaw/*.json\n~/.openclaw/*-credentials*\n~/.openclaw/workspace/memory/*-creds.json\n~/.openclaw/workspace/memory/*credentials*.json\n~/.openclaw/workspace/*/.env\n~/.openclaw/workspace/skills/*/.env\n~/.env (if exists, merges)\n\nSecurity Features\n\n✅ File permissions: Sets .env to mode 600 (owner only) ✅ Directory permissions: Sets backup dirs to mode 700 (owner only) ✅ Backup permissions: Sets backup files to mode 600 (owner only) ✅ Git protection: Creates/updates .gitignore ✅ Backups: Timestamped backups before changes (secured) ✅ Validation: Checks format, permissions, entropy, and duplicates ✅ Template: Creates .env.example (safe to share) ✅ GPG encryption: Encrypts high-value secrets at rest ✅ Rotation tracking: Warns when credentials need rotation ✅ Deep scan: Detects hardcoded secrets in source files ✅ Symlink-aware: Validates symlinked .env targets\n\nOutput Structure\n\nAfter migration:\n\n~/.openclaw/\n├── .env                     # All credentials (secure, mode 600)\n├── .env.secrets.gpg         # GPG-encrypted high-value keys (mode 600)\n├── .env.meta                # Rotation metadata (mode 600)\n├── .env.example             # Template (safe to share)\n├── .gitignore               # Protects .env and .env.secrets.gpg\n└── backups/                 # (mode 700)\n    └── credentials-old-YYYYMMDD/  # (mode 700)\n        └── *.bak            # Backup files (mode 600)\n\nGPG Encryption for High-Value Secrets\n\nPrivate keys, wallet keys, and mnemonics should never exist as plaintext on disk. Use GPG encryption for these.\n\nSetup GPG\n# First-time setup (generates OpenClaw GPG key, configures agent cache)\n./scripts/setup-gpg.sh\n\nEncrypt High-Value Keys\n# Encrypt specific keys (moves them from .env to .env.secrets.gpg)\n./scripts/encrypt.py --keys MAIN_WALLET_PRIVATE_KEY,CUSTODY_PRIVATE_KEY,SIGNER_PRIVATE_KEY\n\n# The .env will contain placeholders:\n# MAIN_WALLET_PRIVATE_KEY=GPG:MAIN_WALLET_PRIVATE_KEY\n\nHow Scripts Access Encrypted Keys\n\nThe enforce.py module handles this transparently:\n\nfrom enforce import get_credential\n\n# Works for both plaintext and GPG-encrypted keys\nkey = get_credential('MAIN_WALLET_PRIVATE_KEY')\n# If value starts with \"GPG:\", decrypts from .env.secrets.gpg automatically\n\nGPG Agent Caching\n\nOn headless servers (VPS), the GPG agent caches the passphrase:\n\nDefault cache TTL: 8 hours\nConfigurable via setup-gpg.sh\nPassphrase required once after reboot, then cached\nWhat to Encrypt\nKey Type\tEncrypt?\tWhy\nWallet private keys\t✅ Yes\tControls funds\nCustody/signer private keys\t✅ Yes\tControls identity\nMnemonics / seed phrases\t✅ Yes\tMaster recovery\nAPI keys (services)\t❌ No\tRevocable, low damage\nAgent IDs, names, URLs\t❌ No\tNot secrets\nCredential Rotation Tracking\nSetup Rotation Metadata\n# Initialize rotation tracking for all keys\n./scripts/rotation-check.py --init\n\n\nCreates ~/.openclaw/.env.meta:\n\n{\n  \"MAIN_WALLET_PRIVATE_KEY\": {\n    \"created\": \"2026-01-15\",\n    \"lastRotated\": null,\n    \"rotationDays\": 90,\n    \"risk\": \"critical\"\n  },\n  \"MOLTBOOK_API_KEY\": {\n    \"created\": \"2026-02-04\",\n    \"lastRotated\": null,\n    \"rotationDays\": 180,\n    \"risk\": \"low\"\n  }\n}\n\nCheck Rotation Status\n# Check which keys need rotation\n./scripts/rotation-check.py\n\n# Output:\n# 🔴 MAIN_WALLET_PRIVATE_KEY: 26 days old (critical, rotate every 90 days)\n# ✅ MOLTBOOK_API_KEY: 7 days old (low, rotate every 180 days)\n\nRotation Schedules\nRisk Level\tRotation Period\tExamples\nCritical\t90 days\tWallet keys, private keys\nStandard\t180 days\tAPI keys for paid services\nLow\t365 days\tFree-tier API keys, agent IDs\nAdd to Heartbeat (Optional)\n\nAdd rotation checks to HEARTBEAT.md for periodic monitoring:\n\n## Credential Rotation (weekly)\nIf 7+ days since last rotation check:\n1. Run: ./scripts/rotation-check.py\n2. If any keys overdue: notify human\n3. Update lastRotationCheck timestamp\n\nSupported Services\n\nCommon services auto-detected:\n\nX (Twitter): OAuth 1.0a credentials\nFarcaster: Custody keys, signer keys, FID credentials\nMolten: Agent intent matching\nMoltbook: Agent social network\nBotchan/4claw: Net Protocol\nOpenAI, Anthropic, Google: AI providers\nGitHub, GitLab: Code hosting\nCoinbase/CDP: Crypto wallet credentials\nGeneric: API_KEY, *_TOKEN, *_SECRET patterns\n\nSee references/supported-services.md for full list.\n\nScripts\n\nAll scripts support --help for detailed usage.\n\nscan.py\n# Scan and report\n./scripts/scan.py\n\n# Deep scan (includes hardcoded secrets in scripts)\n./scripts/scan.py --deep\n\n# Include custom paths\n./scripts/scan.py --paths ~/.myapp/config ~/.local/share/creds\n\n# JSON output\n./scripts/scan.py --format json\n\nconsolidate.py\n# Interactive mode (prompts before changes)\n./scripts/consolidate.py\n\n# Auto-confirm (no prompts)\n./scripts/consolidate.py --yes\n\n# Backup only\n./scripts/consolidate.py --backup-only\n\n# Specific service\n./scripts/consolidate.py --service molten\n\nvalidate.py\n# Full validation (permissions, format, entropy, security)\n./scripts/validate.py\n\n# Check permissions only\n./scripts/validate.py --check permissions\n\n# Fix issues automatically\n./scripts/validate.py --fix\n\nencrypt.py\n# Encrypt specific high-value keys\n./scripts/encrypt.py --keys MAIN_WALLET_PRIVATE_KEY,CUSTODY_PRIVATE_KEY\n\n# List currently encrypted keys\n./scripts/encrypt.py --list\n\n# Decrypt (move back to plaintext .env)\n./scripts/encrypt.py --decrypt --keys MAIN_WALLET_PRIVATE_KEY\n\nrotation-check.py\n# Check rotation status\n./scripts/rotation-check.py\n\n# Initialize tracking for all keys\n./scripts/rotation-check.py --init\n\n# Record a rotation\n./scripts/rotation-check.py --rotated MOLTBOOK_API_KEY\n\nsetup-gpg.sh\n# First-time GPG setup for OpenClaw\n./scripts/setup-gpg.sh\n\n# Configure cache timeout (hours)\n./scripts/setup-gpg.sh --cache-hours 12\n\ncleanup.py\n# Dry run (shows what would be deleted)\n./scripts/cleanup.py\n\n# Actually delete old files\n./scripts/cleanup.py --confirm\n\n# Keep backups\n./scripts/cleanup.py --confirm --keep-backups\n\nMigration Workflow\n\nThis is the exact step-by-step flow, tested and verified on a live OpenClaw deployment.\n\nStep 1: Scan for Scattered Credentials\ncd /path/to/openclaw/skills/credential-manager\n\n# Basic scan — finds credential files by path patterns\n./scripts/scan.py\n\n# Deep scan — also greps source files for hardcoded secrets\n./scripts/scan.py --deep\n\n\nWhat to look for in output:\n\n⚠️ files with mode != 600 (insecure permissions)\nSymlinked .env files (should point to main ~/.openclaw/.env)\nJSON credential files outside ~/.openclaw/.env\nDeep scan hits on hardcoded keys in scripts\n\nExample output:\n\n⚠️ /home/user/.openclaw/farcaster-credentials.json\n   Type: json\n   Keys: custodyPrivateKey, signerPrivateKey, ...\n   Mode: 644\n   ⚠️  Should be 600 for security\n\n✅ /home/user/.openclaw/.env\n   Type: env\n   Keys: API_KEY, X_CONSUMER_KEY, ...\n   Mode: 600\n\nStep 2: Consolidate into .env\n./scripts/consolidate.py\n\n\nInteractive flow:\n\nScript scans and lists all credential files found\nBacks up existing .env to ~/.openclaw/backups/credentials-old-YYYYMMDD/\nLoads existing .env keys\nProcesses each credential file:\nAuto-detects service (x, farcaster, moltbook, molten, etc.)\nNormalizes key names (e.g., custodyPrivateKey → FARCASTER_CUSTODY_PRIVATE_KEY)\nShows mapping: key → ENV_KEY\nAsks for confirmation: Proceed? [y/N]\nWrites merged .env (mode 600)\nCreates .env.example template (safe to share)\nUpdates .gitignore\n\nFor credentials not auto-detected (e.g., nested JSON like farcaster-credentials.json with multiple accounts), manually add to .env:\n\ncat >> ~/.openclaw/.env << 'EOF'\n\n# FARCASTER (Active: mr-teeclaw, FID 2700953)\nFARCASTER_FID=2700953\nFARCASTER_FNAME=mr-teeclaw\nFARCASTER_CUSTODY_ADDRESS=0x...\nFARCASTER_CUSTODY_PRIVATE_KEY=0x...\nFARCASTER_SIGNER_PUBLIC_KEY=...\nFARCASTER_SIGNER_PRIVATE_KEY=...\n\n# FARCASTER LEGACY (teeclaw, FID 2684290)\nFARCASTER_LEGACY_FID=2684290\nFARCASTER_LEGACY_CUSTODY_ADDRESS=0x...\nFARCASTER_LEGACY_CUSTODY_PRIVATE_KEY=0x...\nFARCASTER_LEGACY_SIGNER_PUBLIC_KEY=...\nFARCASTER_LEGACY_SIGNER_PRIVATE_KEY=...\nEOF\n\nchmod 600 ~/.openclaw/.env\n\nStep 3: Validate\n./scripts/validate.py\n\n\nChecks performed:\n\n✅ .env permissions (must be 600)\n✅ .gitignore coverage\n✅ Format validation (key format, quoting, duplicates)\n✅ Security analysis:\nDetects plaintext private keys (0x + 64 hex chars) → recommends GPG\nDetects mnemonic/seed phrases (12/24 word values) → recommends GPG\nEntropy analysis on SECRET/PRIVATE_KEY/PASSWORD fields\nFlags weak/placeholder values\n✅ Backup permissions (files must be 600, directories 700)\n\nFix issues automatically:\n\n./scripts/validate.py --fix\n\n\nThis fixes: file permissions, directory permissions, backup permissions, gitignore. It does NOT auto-fix format issues or encrypt keys — those require manual action.\n\nStep 4: Setup GPG and Encrypt Private Keys\n# First-time GPG setup (configures agent cache, tests encrypt/decrypt)\n./scripts/setup-gpg.sh\n# Optional: --cache-hours 12 (default: 8)\n\n\nEncrypt high-value keys:\n\n# Encrypt wallet + Farcaster private keys\n./scripts/encrypt.py --keys MAIN_WALLET_PRIVATE_KEY,FARCASTER_CUSTODY_PRIVATE_KEY,FARCASTER_SIGNER_PRIVATE_KEY,FARCASTER_LEGACY_CUSTODY_PRIVATE_KEY,FARCASTER_LEGACY_SIGNER_PRIVATE_KEY\n\n\nWhat happens:\n\nPrompts for a GPG passphrase (or reads OPENCLAW_GPG_PASSPHRASE env var)\nExtracts specified key values from .env\nStores them encrypted in ~/.openclaw/.env.secrets.gpg (AES256, mode 600)\nReplaces .env values with GPG:KEY_NAME placeholders\nScripts using get_credential() or _load_cred() decrypt transparently\n\nSave passphrase to .env for automated decryption:\n\necho 'OPENCLAW_GPG_PASSPHRASE=your-passphrase-here' >> ~/.openclaw/.env\nchmod 600 ~/.openclaw/.env\n\n\nVerify encryption:\n\n# Check .env has GPG placeholders\ngrep \"GPG:\" ~/.openclaw/.env\n\n# List all encrypted keys\n./scripts/encrypt.py --list\n\nStep 5: Initialize Rotation Tracking\n./scripts/rotation-check.py --init\n\n\nAuto-classifies all keys by risk:\n\nCritical (90-day rotation): *PRIVATE_KEY, *MNEMONIC, *SEED, *WALLET_KEY, *CUSTODY*, *SIGNER*\nStandard (180-day rotation): *API_KEY, *SECRET, *TOKEN, *BEARER, *CONSUMER*, *ACCESS*\nLow (365-day rotation): Everything else\n\nCreates ~/.openclaw/.env.meta (mode 600) with creation dates and rotation schedules.\n\nCheck rotation status anytime:\n\n./scripts/rotation-check.py\n\nStep 6: Cleanup Old Credential Files\n# Dry run first — see what would be deleted\n./scripts/cleanup.py\n\n# Actually delete (prompts for 'DELETE' confirmation)\n./scripts/cleanup.py --confirm\n\n\nAlso manually remove migrated files not caught by the scanner:\n\n# Example: farcaster-credentials.json was manually migrated\ncp ~/.openclaw/farcaster-credentials.json ~/.openclaw/backups/credentials-old-YYYYMMDD/farcaster-credentials.json.bak\nchmod 600 ~/.openclaw/backups/credentials-old-YYYYMMDD/farcaster-credentials.json.bak\nrm ~/.openclaw/farcaster-credentials.json\n\nStep 7: Update Scripts That Referenced Old Files\n\nAny scripts that loaded from JSON credential files or hardcoded paths need updating.\n\nPattern — Bash scripts:\n\n# OLD (insecure):\nFARCASTER_CREDS=\"/home/user/.openclaw/farcaster-credentials.json\"\nfid=$(jq -r '.fid' \"$FARCASTER_CREDS\")\nprivate_key=$(jq -r '.custodyPrivateKey' \"$FARCASTER_CREDS\")\n\n# NEW (secure, GPG-aware):\nENV_FILE=\"$HOME/.openclaw/.env\"\n\n_load_cred() {\n  local key=\"$1\"\n  local value\n  value=$(grep \"^${key}=\" \"$ENV_FILE\" | head -1 | cut -d= -f2-)\n  if [[ \"$value\" == GPG:* ]]; then\n    local gpg_key=\"${value#GPG:}\"\n    local passphrase=\"${OPENCLAW_GPG_PASSPHRASE:-}\"\n    if [ -n \"$passphrase\" ]; then\n      value=$(echo \"$passphrase\" | gpg -d --batch --quiet --passphrase-fd 0 \"$HOME/.openclaw/.env.secrets.gpg\" | python3 -c \"import json,sys; print(json.load(sys.stdin).get('$gpg_key',''))\")\n    else\n      value=$(gpg -d --batch --quiet \"$HOME/.openclaw/.env.secrets.gpg\" | python3 -c \"import json,sys; print(json.load(sys.stdin).get('$gpg_key',''))\")\n    fi\n  fi\n  echo \"$value\"\n}\n\nfid=$(_load_cred \"FARCASTER_FID\")\nprivate_key=$(_load_cred \"FARCASTER_CUSTODY_PRIVATE_KEY\")\n\n\nPattern — Node.js scripts:\n\n// OLD (insecure):\nconst creds = JSON.parse(fs.readFileSync('~/.openclaw/farcaster-credentials.json'));\nconst privateKey = creds.custodyPrivateKey;\n\n// NEW (secure, GPG-aware):\nconst ENV_PATH = path.join(os.homedir(), '.openclaw/.env');\nconst SECRETS_PATH = path.join(os.homedir(), '.openclaw/.env.secrets.gpg');\n\nfunction loadCred(key) {\n  const content = fs.readFileSync(ENV_PATH, 'utf8');\n  for (const line of content.split('\\n')) {\n    if (line.startsWith(key + '=')) {\n      let value = line.slice(key.length + 1).trim();\n      if (value.startsWith('GPG:')) {\n        const { execSync } = require('child_process');\n        const passphrase = process.env.OPENCLAW_GPG_PASSPHRASE || '';\n        const cmd = passphrase\n          ? `echo \"${passphrase}\" | gpg -d --batch --quiet --passphrase-fd 0 \"${SECRETS_PATH}\"`\n          : `gpg -d --batch --quiet \"${SECRETS_PATH}\"`;\n        const secrets = JSON.parse(execSync(cmd, { encoding: 'utf8' }));\n        return secrets[value.slice(4)] || '';\n      }\n      return value;\n    }\n  }\n  return '';\n}\n\nconst privateKey = loadCred('FARCASTER_CUSTODY_PRIVATE_KEY');\n\n\nPattern — Python scripts:\n\n# Use the enforce module (recommended):\nimport sys\nfrom pathlib import Path\nsys.path.insert(0, str(Path.home() / 'openclaw/skills/credential-manager/scripts'))\nfrom enforce import get_credential\n\nprivate_key = get_credential('FARCASTER_CUSTODY_PRIVATE_KEY')  # Auto-decrypts GPG\n\nStep 8: Final Validation\n# Run full validation — should show all green\n./scripts/validate.py\n\n# Verify encrypted keys\n./scripts/encrypt.py --list\n\n# Check rotation status\n./scripts/rotation-check.py\n\n# Test a script that uses credentials\nbash /path/to/your/script.sh\n\n\nExpected final state:\n\n~/.openclaw/\n├── .env                     # All credentials (mode 600, private keys = GPG:*)\n├── .env.secrets.gpg         # GPG-encrypted private keys (mode 600)\n├── .env.meta                # Rotation tracking metadata (mode 600)\n├── .env.example             # Template (safe to share)\n├── .gitignore               # Protects .env, .env.secrets.gpg, .env.meta\n└── backups/                 # (mode 700)\n    └── credentials-old-YYYYMMDD/  # (mode 700)\n        └── *.bak            # Backup files (mode 600)\n\nFor Skill Developers: Enforce This Standard\n\nOther OpenClaw skills MUST validate credentials are secure before using them:\n\nPython Skills\n#!/usr/bin/env python3\nimport sys\nfrom pathlib import Path\n\n# Add credential-manager scripts to path\nsys.path.insert(0, str(Path.home() / '.openclaw/skills/credential-manager/scripts'))\n\n# Enforce secure .env (exits if not compliant)\nfrom enforce import require_secure_env, get_credential\n\nrequire_secure_env()\n\n# Now safe to load credentials (handles GPG-encrypted keys transparently)\napi_key = get_credential('SERVICE_API_KEY')\nwallet_key = get_credential('MAIN_WALLET_PRIVATE_KEY')  # Auto-decrypts from GPG\n\nBash Skills\n#!/usr/bin/env bash\nset -euo pipefail\n\n# Validate .env exists and is secure\nif ! python3 ~/.openclaw/skills/credential-manager/scripts/enforce.py; then\n    exit 1\nfi\n\n# Now safe to load\nsource ~/.openclaw/.env\n\n\nThis creates a fail-fast system: If credentials aren't properly secured, skills refuse to run. Users are forced to fix it.\n\nLoading Credentials\n\nAfter migration, load from .env:\n\nPython\nimport os\nfrom pathlib import Path\n\n# Load .env\nenv_file = Path.home() / '.openclaw' / '.env'\nwith open(env_file) as f:\n    for line in f:\n        if '=' in line and not line.strip().startswith('#'):\n            key, val = line.strip().split('=', 1)\n            os.environ[key] = val\n\n# Use credentials\napi_key = os.getenv('SERVICE_API_KEY')\n\nBash\n# Load .env\nset -a\nsource ~/.openclaw/.env\nset +a\n\n# Use credentials\necho \"$SERVICE_API_KEY\"\n\nUsing Existing Loaders\n\nIf you migrated using OpenClaw scripts:\n\nfrom load_credentials import get_credentials\ncreds = get_credentials('x')\n\nAdding New Credentials\n\nEdit ~/.openclaw/.env:\n\n# Add new service\nNEW_SERVICE_API_KEY=your_key_here\nNEW_SERVICE_SECRET=your_secret_here\n\n\nUpdate template too:\n\n# Edit .env.example\nNEW_SERVICE_API_KEY=your_key_here\nNEW_SERVICE_SECRET=your_secret_here\n\n\nIf the new credential is high-value (private key, wallet key):\n\n# Add to .env first, then encrypt\n./scripts/encrypt.py --keys NEW_SERVICE_PRIVATE_KEY\n\nSecurity Best Practices\n\nSee references/security.md for detailed security guidelines.\n\nQuick checklist:\n\n✅ .env has 600 permissions\n✅ .env is git-ignored\n✅ Backup files have 600 permissions\n✅ Backup directories have 700 permissions\n✅ No credentials in code or logs (use --deep scan to verify)\n✅ Private keys encrypted with GPG\n✅ Rotation schedule established and tracked\n✅ Symlinked .env files point to the main .env only\n✅ No credentials in shell history (use source, not export KEY=val)\nRollback\n\nIf something goes wrong:\n\n# Find your backup\nls -la ~/.openclaw/backups/\n\n# Restore specific file\ncp ~/.openclaw/backups/credentials-old-YYYYMMDD/x-credentials.json.bak \\\n   ~/.config/x/credentials.json\n\n# Decrypt GPG secrets back to plaintext\n./scripts/encrypt.py --decrypt --keys MAIN_WALLET_PRIVATE_KEY\n\nNotes\nNon-destructive by default: Original files backed up before removal\nIdempotent: Safe to run multiple times\nExtensible: Add custom credential patterns in scripts\nSecure: Never logs full credentials, only metadata\nGPG-aware: Transparently handles encrypted and plaintext credentials\nBackup-hardened: All backups secured with proper permissions\nSymlink-aware: Detects and validates symlinked credential files"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/teeclaw/openclaw-credential-manager",
    "publisherUrl": "https://clawhub.ai/teeclaw/openclaw-credential-manager",
    "owner": "teeclaw",
    "version": "2.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/openclaw-credential-manager",
    "downloadUrl": "https://openagent3.xyz/downloads/openclaw-credential-manager",
    "agentUrl": "https://openagent3.xyz/skills/openclaw-credential-manager/agent",
    "manifestUrl": "https://openagent3.xyz/skills/openclaw-credential-manager/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/openclaw-credential-manager/agent.md"
  }
}