setup
Facilitates the setup of the claude-ops plugin by configuring channels and installing necessary CLIs through an interactive wizard.
Install this skill
Security score
The setup skill was audited on May 29, 2026 and we found 267 security issues across 5 threat categories, including 1 critical. Review the findings below before installing.
Categories Tested
Security Issues
Direct command execution function call
| 2304 | On `[Deep hunt — spawn agent]`, spawn (background, Rule 4): |
Template literal with variable interpolation in command context
| 53 | - **`$PREFS_PATH`** — per-user preferences + secrets. Resolves to `${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/preferences.json`. Lives in Claude Code's plugin data dir s |
Template literal with variable interpolation in command context
| 54 | - **`${CLAUDE_PLUGIN_ROOT}/scripts/registry.json`** — per-user project registry (gitignored in the source repo). `mkdir -p` its parent if missing. |
Template literal with variable interpolation in command context
| 55 | - **`${CLAUDE_PLUGIN_ROOT}/.mcp.json`** — only to add `${user_config.*}` placeholders, never hardcoded tokens. |
Template literal with variable interpolation in command context
| 86 | ```bash |
Template literal with variable interpolation in command context
| 96 | ```! |
Template literal with variable interpolation in command context
| 123 | ```! |
Template literal with variable interpolation in command context
| 131 | ```bash |
Template literal with variable interpolation in command context
| 227 | ```bash |
Template literal with variable interpolation in command context
| 306 | - **Linux / WSL** (`OS=linux|wsl`): `launchctl` is not available. The daemon script (`${CLAUDE_PLUGIN_ROOT}/scripts/ops-daemon.sh`) runs fine under `bash`, but installing it as a user service requires |
Template literal with variable interpolation in command context
| 308 | ``` |
Template literal with variable interpolation in command context
| 336 | ```bash |
Template literal with variable interpolation in command context
| 367 | # /ops:go is instant. `memory-extractor` runs but stays idle until channels exist. |
Template literal with variable interpolation in command context
| 409 | > **Deep-dive:** see `${CLAUDE_PLUGIN_ROOT}/docs/daemon-guide.md` for full operational instructions, CLI reference, and troubleshooting for the background daemon. The setup agent can load that file di |
Template literal with variable interpolation in command context
| 587 | - Placeholder values like `${user_config.*}`, `<your-token>`, `CHANGE_ME`, or empty strings count as NOT FOUND. |
Template literal with variable interpolation in command context
| 684 | ```bash |
Template literal with variable interpolation in command context
| 699 | 6. **Wait for the script to exit.** Poll until the process is no longer running (`ps -p "$(cat /tmp/ops-telegram-autolink.pid)"`). Read `/tmp/ops-telegram-autolink.out` — it should contain a single JS |
Template literal with variable interpolation in command context
| 721 | ```bash |
Template literal with variable interpolation in command context
| 747 | ```bash |
Template literal with variable interpolation in command context
| 766 | 9. **Smoke test (optional).** Spawn `node ${CLAUDE_PLUGIN_ROOT}/telegram-server/index.js` with the env vars set inline for 3 seconds. If it doesn't print an auth error, the session works. |
Template literal with variable interpolation in command context
| 774 | > **Deep-dive:** see `${CLAUDE_PLUGIN_ROOT}/skills/ops-comms/SKILL.md` for full operational instructions, CLI reference, and troubleshooting for this integration. The setup agent can load that file di |
Template literal with variable interpolation in command context
| 908 | ```bash |
Template literal with variable interpolation in command context
| 915 | ```bash |
Template literal with variable interpolation in command context
| 989 | > **Deep-dive:** see `${CLAUDE_PLUGIN_ROOT}/skills/ops-comms/SKILL.md` and `${CLAUDE_PLUGIN_ROOT}/skills/ops-inbox/SKILL.md` for full operational instructions, CLI reference, and troubleshooting for t |
Template literal with variable interpolation in command context
| 1053 | > **Deep-dive:** see `${CLAUDE_PLUGIN_ROOT}/skills/ops-inbox/SKILL.md` and `${CLAUDE_PLUGIN_ROOT}/skills/ops-comms/SKILL.md` for full operational instructions, CLI reference, and troubleshooting for t |
Template literal with variable interpolation in command context
| 1073 | ```bash |
Template literal with variable interpolation in command context
| 1086 | ```bash |
Template literal with variable interpolation in command context
| 1097 | - `[Install Playwright now]` → run `cd ${CLAUDE_PLUGIN_ROOT}/telegram-server && npm install playwright && npx playwright install chromium` (background, ~150MB download, report progress). |
Template literal with variable interpolation in command context
| 1131 | > **Deep-dive:** see `${CLAUDE_PLUGIN_ROOT}/skills/ops-comms/SKILL.md` and `${CLAUDE_PLUGIN_ROOT}/skills/ops-inbox/SKILL.md` for full operational instructions, CLI reference, and troubleshooting for t |
Template literal with variable interpolation in command context
| 1207 | > **Deep-dive:** see `${CLAUDE_PLUGIN_ROOT}/skills/ops-inbox/CHANNELS.md` for full Notion MCP tool reference and troubleshooting. |
Template literal with variable interpolation in command context
| 1250 | 7. On "Install gog instead", **run the install via Bash** (Rule 2) using the same npm → bun → source-clone chain as Step 3c — either inline the snippet or call `${CLAUDE_PLUGIN_ROOT}/bin/ops-setup-ins |
Template literal with variable interpolation in command context
| 1268 | > **Deep-dive:** see `${CLAUDE_PLUGIN_ROOT}/skills/ops-go/SKILL.md` for full operational instructions, CLI reference, and troubleshooting for this integration (calendar context feeds `/ops:go` briefin |
Template literal with variable interpolation in command context
| 1391 | > **Deep-dive:** no dedicated skill ships with Doppler — see `${CLAUDE_PLUGIN_ROOT}/docs/memories-system.md` (Runtime Context section) for how downstream skills consume the `secrets_manager` / `dopple |
Template literal with variable interpolation in command context
| 1411 | 3. **Save token to userConfig**: Write the token to `doppler_token` in the plugin's `userConfig` (this feeds `.mcp.json` at runtime via `${user_config.doppler_token}`). Also save `doppler_project` and |
Template literal with variable interpolation in command context
| 1615 | > **Deep-dive:** no dedicated skill ships with the password manager integration — see `${CLAUDE_PLUGIN_ROOT}/docs/memories-system.md` (Runtime Context section) for how downstream skills resolve `passw |
Template literal with variable interpolation in command context
| 1724 | ```bash |
Template literal with variable interpolation in command context
| 1808 | > **Deep-dive:** see `${CLAUDE_PLUGIN_ROOT}/skills/ops-ecom/SKILL.md` for full operational instructions, CLI reference, and troubleshooting for the ecommerce integration (multi-store Shopify, partner |
Template literal with variable interpolation in command context
| 1913 | ```bash |
Template literal with variable interpolation in command context
| 1929 | ```bash |
Template literal with variable interpolation in command context
| 1945 | ```bash |
Template literal with variable interpolation in command context
| 1960 | ```bash |
Template literal with variable interpolation in command context
| 2033 | ```bash |
Template literal with variable interpolation in command context
| 2103 | > **Deep-dive:** see `${CLAUDE_PLUGIN_ROOT}/skills/ops-marketing/SKILL.md` for full operational instructions, CLI reference, and troubleshooting for marketing integrations (Klaviyo flows, Meta Ads, GA |
Template literal with variable interpolation in command context
| 2202 | > **Deep-dive:** see `${CLAUDE_PLUGIN_ROOT}/skills/ops-voice/SKILL.md` for full operational instructions, CLI reference, and troubleshooting for voice integrations (Bland AI call flows, ElevenLabs TTS |
Template literal with variable interpolation in command context
| 2353 | > **Deep-dive:** see `${CLAUDE_PLUGIN_ROOT}/skills/ops-revenue/SKILL.md` for full operational instructions, CLI reference, and troubleshooting for revenue integrations (Stripe MRR/ARR queries, Revenue |
Template literal with variable interpolation in command context
| 2461 | > **Deep-dive:** see `${CLAUDE_PLUGIN_ROOT}/docs/notifications.md`, `${CLAUDE_PLUGIN_ROOT}/scripts/ops-fires-watcher.sh`, and `${CLAUDE_PLUGIN_ROOT}/scripts/ops-notify.sh` for sink priority rationale, |
Template literal with variable interpolation in command context
| 2469 | ```bash |
Template literal with variable interpolation in command context
| 2583 | > **Deep-dive:** see `${CLAUDE_PLUGIN_ROOT}/skills/ops-comms/SKILL.md` (Discord send/read sections) and `${CLAUDE_PLUGIN_ROOT}/bin/ops-discord` for full operational instructions and subcommand referen |
Template literal with variable interpolation in command context
| 2612 | > **Deep-dive:** see `${CLAUDE_PLUGIN_ROOT}/skills/ops-linear/SKILL.md`, `${CLAUDE_PLUGIN_ROOT}/skills/ops-triage/SKILL.md`, and `${CLAUDE_PLUGIN_ROOT}/skills/ops-fires/SKILL.md` for full operational |
Template literal with variable interpolation in command context
| 2618 | > **Templates:** a pre-baked starter for common stacks lives in `${CLAUDE_PLUGIN_ROOT}/scripts/registry.templates/`. If you want to start from one, `cp "${CLAUDE_PLUGIN_ROOT}/scripts/registry.template |
Template literal with variable interpolation in command context
| 2651 | ```! |
Template literal with variable interpolation in command context
| 2671 | ```bash |
Template literal with variable interpolation in command context
| 2711 | - Ensure the registry directory exists: `mkdir -p "${CLAUDE_PLUGIN_ROOT}/scripts"`. If the write fails due to permissions (plugin cache dirs can be read-only), fall back to writing at `$DATA_DIR/regis |
Template literal with variable interpolation in command context
| 2716 | > **Deep-dive:** see `${CLAUDE_PLUGIN_ROOT}/skills/ops-projects/SKILL.md` for full operational instructions, CLI reference, and troubleshooting for the project registry (auto-discovery, registry schem |
Template literal with variable interpolation in command context
| 2732 | ```bash |
Template literal with variable interpolation in command context
| 2791 | Write daemon services config to `$DATA_DIR/daemon-services.json` — merge with the existing config from Step 2c, preserving `briefing-pre-warm` and `memory-extractor`, and enabling the new channel-depe |
Template literal with variable interpolation in command context
| 2792 | - `briefing-pre-warm`: `{ "enabled": true, "command": "${CLAUDE_PLUGIN_ROOT}/bin/ops-gather", "cron": "*/2 * * * *" }` — pre-warms /ops:go cache (installed in 2c) |
Template literal with variable interpolation in command context
| 2793 | - `wacli-sync`: `{ "enabled": true, "command": "${CLAUDE_PLUGIN_ROOT}/scripts/wacli-keepalive.sh", "health_file": "~/.wacli/.health", "restart_delay": 60, "max_restarts": 10 }` — only if WhatsApp conf |
Template literal with variable interpolation in command context
| 2794 | - `memory-extractor`: `{ "enabled": true, "command": "${CLAUDE_PLUGIN_ROOT}/scripts/ops-memory-extractor.sh", "health_file": "~/.claude/plugins/data/ops-ops-marketplace/memories/.health", "cron": "*/3 |
Template literal with variable interpolation in command context
| 2795 | - `inbox-digest`: `{ "enabled": true, "command": "${CLAUDE_PLUGIN_ROOT}/scripts/ops-cron-inbox-digest.sh", "cron": "0 */4 * * *" }` — every 4h |
Template literal with variable interpolation in command context
| 2796 | - `store-health`: `{ "enabled": true, "command": "${CLAUDE_PLUGIN_ROOT}/scripts/ops-cron-store-health.sh", "cron": "0 9 * * *" }` — daily 9am, only if ecom configured |
Template literal with variable interpolation in command context
| 2797 | - `competitor-intel`: `{ "enabled": true, "command": "${CLAUDE_PLUGIN_ROOT}/scripts/ops-cron-competitor-intel.sh", "cron": "0 10 * * 1" }` — weekly Monday 10am |
Template literal with variable interpolation in command context
| 2798 | - `message-listener`: `{ "enabled": true, "command": "${CLAUDE_PLUGIN_ROOT}/scripts/ops-message-listener.sh" }` — only if WhatsApp or Telegram configured |
Template literal with variable interpolation in command context
| 2823 | > **Deep-dive:** see `${CLAUDE_PLUGIN_ROOT}/docs/daemon-guide.md` for full operational instructions, CLI reference, and troubleshooting for the background daemon (service lifecycle, launchctl/systemd |
Template literal with variable interpolation in command context
| 2937 | ```bash |
Curl to non-GitHub URL
| 1102 | curl -s -H "Authorization: Bearer XOXC_TOKEN" -b "d=XOXD_TOKEN" "https://slack.com/api/auth.test" |
Curl to non-GitHub URL
| 1194 | curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $NOTION_API_KEY" -H "Notion-Version: 2022-06-28" https://api.notion.com/v1/users/me | grep -q "200" && echo "OK" || echo "FAIL" |
Curl to non-GitHub URL
| 1293 | | Debian / Ubuntu | `curl -Ls https://cli.doppler.com/install.sh \| sudo sh` | |
Curl to non-GitHub URL
| 1890 | curl -s "https://graph.facebook.com/v20.0/$AD_ACCOUNT_ID/campaigns?access_token=$TOKEN&limit=1" | jq '.data | length' |
Curl to non-GitHub URL
| 1930 | TOKEN_RESP=$(curl -s -X POST https://oauth2.googleapis.com/token \ |
Curl to non-GitHub URL
| 1946 | ACCESS_TOKEN=$(curl -s -X POST https://oauth2.googleapis.com/token \ |
Curl to non-GitHub URL
| 1961 | curl -s -X GET "https://googleads.googleapis.com/v23/customers:listAccessibleCustomers" \ |
Curl to non-GitHub URL
| 2034 | curl -s "https://graph.facebook.com/v20.0/${WABA_PHONE_ID}" \ |
Curl to non-GitHub URL
| 2153 | curl -s -H "Authorization: $KEY" "https://api.bland.ai/v1/me" | jq '.user.id' |
Curl to non-GitHub URL
| 2167 | curl -s -H "xi-api-key: $KEY" "https://api.elevenlabs.io/v1/user" | jq '.subscription.tier' |
Curl to non-GitHub URL
| 2288 | curl -s -u "$STRIPE_SECRET_KEY:" "https://api.stripe.com/v1/balance" | jq '.available | length' |
Curl to non-GitHub URL
| 2417 | curl -s -X POST https://api.pushover.net/1/messages.json \ |
Curl to non-GitHub URL
| 2542 | curl -sS "https://discord.com/api/v10/users/@me" \ |
Curl to non-GitHub URL
| 3112 | curl -s -H "Authorization: Bearer XOXC_TOKEN" -b "d=XOXD_TOKEN" "https://slack.com/api/auth.test" |
Webhook reference - potential data exfiltration
| 1751 | - What credentials are needed (API key, OAuth token, webhook secret, base URL, account ID, etc.) |
Webhook reference - potential data exfiltration
| 2366 | DISCORD_WEBHOOK_URL NTFY_TOPIC PUSHOVER_USER PUSHOVER_TOKEN 2>/dev/null |
Webhook reference - potential data exfiltration
| 2369 | | map(select(.key | test("telegram_bot_token|telegram_notify_chat_id|discord_webhook_url|ntfy_topic|pushover_user_key|pushover_app_token"))) |
Webhook reference - potential data exfiltration
| 2394 | | Also add Discord webhook | discord | Fan out to a #incidents channel in addition to X. | |
Webhook reference - potential data exfiltration
| 2426 | **Discord** — if the user already set `discord_default_webhook_url` via a prior run (or issue #20's work), reuse it; otherwise Rule-3-prompt for a webhook URL (`https://discord.com/api/webhooks/...`). |
Webhook reference - potential data exfiltration
| 2463 | ### 3m — Discord (webhook + optional bot) |
Webhook reference - potential data exfiltration
| 2465 | Discord is a v1 integration — webhook-based send + REST channel reads. DM + gateway support are deferred to a v2 issue. The send-side webhook also supplies the Discord notification sink consumed by `s |
Webhook reference - potential data exfiltration
| 2471 | printenv DISCORD_BOT_TOKEN DISCORD_WEBHOOK_URL DISCORD_GUILD_ID 2>/dev/null |
Webhook reference - potential data exfiltration
| 2474 | grep -hE 'DISCORD_(BOT_TOKEN|WEBHOOK|GUILD_ID)' ~/.zshrc ~/.bashrc ~/.zprofile ~/.envrc 2>/dev/null | grep -v '^#' |
Webhook reference - potential data exfiltration
| 2498 | Cache these results. Also check `$PREFS_PATH` under `discord.*` and `discord_webhook_url` (the flat key shared with ops-notify.sh) — if any of `discord.bot_token`, `discord.default_webhook_url`, or `d |
Webhook reference - potential data exfiltration
| 2502 | Present via the Universal Credential Auto-Scan prompt format with `[Use this value]` / `[Paste a different one]` / `[Skip]`. If a webhook URL was found but no bot token, note that reads + channel list |
Webhook reference - potential data exfiltration
| 2509 | [Paste webhook URL only] |
Webhook reference - potential data exfiltration
| 2521 | prompt: "Grep the filesystem under $HOME (excluding node_modules, .git, Library/Caches) for Discord credentials. Patterns: bot tokens look like base64 segments separated by dots (e.g. MTAxXXXX.YYYYYY. |
Webhook reference - potential data exfiltration
| 2549 | On `[Paste webhook URL only]`: |
Webhook reference - potential data exfiltration
| 2552 | Enter a default Discord Webhook URL: |
Webhook reference - potential data exfiltration
| 2553 | Find it: Discord → Server Settings → Integrations → Webhooks → New Webhook → Copy URL |
Webhook reference - potential data exfiltration
| 2554 | Format: https://discord.com/api/webhooks/<ID>/<TOKEN> |
Webhook reference - potential data exfiltration
| 2557 | Smoke test — do NOT send content to the webhook during setup. Instead, issue a GET to confirm the URL resolves to webhook metadata: |
Webhook reference - potential data exfiltration
| 2560 | curl -sS -o /dev/null -w '%{http_code}\n' -X GET "$DISCORD_WEBHOOK_URL" |
Webhook reference - potential data exfiltration
| 2563 | Expect `200` (webhook metadata returned) or `401` (valid URL, token invalid — user needs to re-copy). |
Webhook reference - potential data exfiltration
| 2574 | "default_webhook_url": "doppler:DISCORD_WEBHOOK_URL", |
Webhook reference - potential data exfiltration
| 2577 | "discord_webhook_url": "doppler:DISCORD_WEBHOOK_URL" |
Webhook reference - potential data exfiltration
| 2581 | Mirror the webhook to the flat `discord_webhook_url` key so `scripts/ops-notify.sh` (the existing fires sink) continues to find it. Prefer a Doppler reference over raw tokens when Doppler is configure |
Access to hidden dotfiles in home directory
| 56 | - The user's shell profile (`~/.zshrc` etc.) — append-only, never rewrite. |
Access to hidden dotfiles in home directory
| 57 | - At the top of every wizard step, make sure `$PREFS_PATH`'s parent directory exists: `mkdir -p "$(dirname "$PREFS_PATH")"`. Claude Code creates `~/.claude/plugins/data/ops-ops-marketplace/` on plugin |
Access to hidden dotfiles in home directory
| 127 | If `CLAUDE_PLUGIN_ROOT` is unset, fall back to the latest installed cache dir at `~/.claude/plugins/cache/ops-marketplace/ops/<latest-version>/`. Store the resolved path as `PLUGIN_ROOT` for the rest |
Access to hidden dotfiles in home directory
| 142 | Shell: zsh → ~/.zshrc |
Access to hidden dotfiles in home directory
| 246 | find ~/.claude -name "gsd-progress" -path "*/skills/*" 2>/dev/null | head -1 | grep -q . && echo "installed" || echo "not_installed" |
Access to hidden dotfiles in home directory
| 382 | "health_file": "~/.claude/plugins/data/ops-ops-marketplace/memories/.health", |
Access to hidden dotfiles in home directory
| 524 | 2. **Shell profile files** — grep `~/.zshrc`, `~/.bashrc`, `~/.zprofile`, `~/.config/fish/config.fish`, `~/.envrc` (direnv) for `<VAR>=` or `export <VAR>=`. Show the file path next to the value so the |
Access to hidden dotfiles in home directory
| 544 | 6. **OpenClaw config** — if `~/.openclaw/openclaw.json` exists: |
Access to hidden dotfiles in home directory
| 546 | jq -r --arg var "$VAR" '.agents.defaults.env[$var] // empty' ~/.openclaw/openclaw.json 2>/dev/null |
Access to hidden dotfiles in home directory
| 577 | [A] shell env + ~/.zshrc + Dashlane — shpat_508b...682e (matched across 3 sources) |
Access to hidden dotfiles in home directory
| 585 | - **Always collapse matching sources** into one option with `(matched in env + ~/.zshrc + Dashlane)` appended. This is critical to stay within the 4-option limit. |
Access to hidden dotfiles in home directory
| 609 | 6. All shell profile files (~/.zshrc, ~/.bashrc, ~/.zprofile, ~/.envrc, ~/.config/fish/*) |
Access to hidden dotfiles in home directory
| 620 | **On selection**, use the chosen value as the source of truth and — with the user's consent — optionally propagate it back to the other sources (e.g. "Also update ~/.zshrc and Doppler to match?"). Def |
Access to hidden dotfiles in home directory
| 654 | 1. Scans scout sources (keychain → ~/.claude.json → shell profiles → Doppler) for previously-extracted `TELEGRAM_API_ID` / `TELEGRAM_API_HASH` / `TELEGRAM_SESSION`. |
Access to hidden dotfiles in home directory
| 669 | Also check `~/.claude.json mcpServers.telegram.env.TELEGRAM_API_ID`. If all 4 are found and the stored `TELEGRAM_SESSION` decodes as a StringSession, tell the user `"✓ Telegram already configured (api |
Access to hidden dotfiles in home directory
| 745 | Also update `~/.claude.json` MCP server config if the telegram server entry exists — inject the credentials as env vars: |
Access to hidden dotfiles in home directory
| 957 | Health: ~/.wacli/.health | Logs: ~/.claude/plugins/data/ops-ops-marketplace/logs/ |
Access to hidden dotfiles in home directory
| 976 | All ops skills that use WhatsApp (`ops-inbox`, `ops-comms`, `ops-go`) MUST check `~/.wacli/.health` before attempting wacli commands. If `status=needs_auth` or `status=needs_reauth`: |
Access to hidden dotfiles in home directory
| 997 | `gog` is the email + calendar CLI that `ops-inbox` and `ops-comms` call by default. It's a self-contained binary with its own OAuth token at `~/.gog/token.json` — full read + send permissions, no Clau |
Access to hidden dotfiles in home directory
| 1060 | - `~/.claude.json mcpServers.slack.env` (where Claude Code stores them) |
Access to hidden dotfiles in home directory
| 1063 | - Shell profile files (`~/.zshrc`, `~/.bashrc`, `~/.zprofile`, `~/.envrc`) |
Access to hidden dotfiles in home directory
| 1114 | in ~/.claude.json. Since this skill can't write to ~/.claude.json directly, |
Access to hidden dotfiles in home directory
| 1121 | (The reason we don't auto-write: per user-level feedback, ~/.claude.json is a Claude Code internal file and the plugin must not touch it. MCP registration is Claude Code's responsibility.) |
Access to hidden dotfiles in home directory
| 1149 | 2. **Check for self-hosted Notion MCP server.** Look in `~/.claude/settings.json` for `mcpServers.notion` or any entry with `notion` in its args/command. |
Access to hidden dotfiles in home directory
| 1185 | 4. Add MCP server config to `~/.claude/settings.json` under `mcpServers.notion` |
Access to hidden dotfiles in home directory
| 1202 | 1. Set `NOTION_MCP_ENABLED=true` in `~/.claude/settings.json` env section |
Access to hidden dotfiles in home directory
| 1632 | grep -h 'SHOPIFY\|myshopify' ~/.zshrc ~/.bashrc ~/.zprofile ~/.envrc 2>/dev/null | grep -v '^#' |
Access to hidden dotfiles in home directory
| 1648 | jq -r '.agents.defaults.env | to_entries[] | select(.key | test("SHOPIFY")) | "\(.key)=\(.value)"' ~/.openclaw/openclaw.json 2>/dev/null |
Access to hidden dotfiles in home directory
| 1822 | grep -h 'KLAVIYO\|META_\|FACEBOOK\|GA4\|GA_MEASUREMENT\|GOOGLE_ADS' ~/.zshrc ~/.bashrc ~/.zprofile ~/.envrc 2>/dev/null | grep -v '^#' |
Access to hidden dotfiles in home directory
| 1836 | jq -r '.agents.defaults.env | to_entries[] | select(.key | test("KLAVIYO|META_|FACEBOOK|GA4")) | "\(.key)=\(.value)"' ~/.openclaw/openclaw.json 2>/dev/null |
Access to hidden dotfiles in home directory
| 2116 | grep -h 'BLAND\|ELEVENLABS\|GROQ' ~/.zshrc ~/.bashrc ~/.zprofile ~/.envrc 2>/dev/null | grep -v '^#' |
Access to hidden dotfiles in home directory
| 2130 | jq -r '.agents.defaults.env | to_entries[] | select(.key | test("BLAND|ELEVENLABS|GROQ")) | "\(.key)=\(.value)"' ~/.openclaw/openclaw.json 2>/dev/null |
Access to hidden dotfiles in home directory
| 2215 | grep -h 'STRIPE\|REVENUECAT\|RC_API' ~/.zshrc ~/.bashrc ~/.zprofile ~/.envrc 2>/dev/null | grep -v '^#' |
Access to hidden dotfiles in home directory
| 2241 | jq -r '.agents.defaults.env | to_entries[] | select(.key | test("STRIPE|REVENUECAT")) | "\(.key)=\(.value)"' ~/.openclaw/openclaw.json 2>/dev/null |
Access to hidden dotfiles in home directory
| 2272 | prompt: "Grep the filesystem under $HOME (excluding node_modules, .git, Library/Caches) for Stripe secret key patterns: sk_live_[A-Za-z0-9]+ and sk_test_[A-Za-z0-9]+. Also scan ~/.config, ~/.aws, ~/.d |
Access to hidden dotfiles in home directory
| 2447 | ~/.claude/plugins/data/ops-ops-marketplace/daemon-services.json \ |
Access to hidden dotfiles in home directory
| 2449 | mv /tmp/daemon-services.json.new ~/.claude/plugins/data/ops-ops-marketplace/daemon-services.json && \ |
Access to hidden dotfiles in home directory
| 2456 | cat ~/.claude/plugins/data/ops-ops-marketplace/fires-watcher.health 2>/dev/null |
Access to hidden dotfiles in home directory
| 2474 | grep -hE 'DISCORD_(BOT_TOKEN|WEBHOOK|GUILD_ID)' ~/.zshrc ~/.bashrc ~/.zprofile ~/.envrc 2>/dev/null | grep -v '^#' |
Access to hidden dotfiles in home directory
| 2521 | prompt: "Grep the filesystem under $HOME (excluding node_modules, .git, Library/Caches) for Discord credentials. Patterns: bot tokens look like base64 segments separated by dots (e.g. MTAxXXXX.YYYYYY. |
Access to hidden dotfiles in home directory
| 2758 | tail -20 ~/.claude/plugins/data/ops-ops-marketplace/logs/ops-daemon.log |
Access to hidden dotfiles in home directory
| 2793 | - `wacli-sync`: `{ "enabled": true, "command": "${CLAUDE_PLUGIN_ROOT}/scripts/wacli-keepalive.sh", "health_file": "~/.wacli/.health", "restart_delay": 60, "max_restarts": 10 }` — only if WhatsApp conf |
Access to hidden dotfiles in home directory
| 2794 | - `memory-extractor`: `{ "enabled": true, "command": "${CLAUDE_PLUGIN_ROOT}/scripts/ops-memory-extractor.sh", "health_file": "~/.claude/plugins/data/ops-ops-marketplace/memories/.health", "cron": "*/3 |
Access to hidden dotfiles in home directory
| 2901 | 2. If missing, **append it automatically** — this is a required step, not optional. Use `>>` (append, never overwrite). Print: `"✓ Added export CLAUDE_PLUGIN_ROOT=... to ~/.zshrc"`. Do NOT ask the use |
Access to hidden dotfiles in home directory
| 2902 | 3. Tell the user: `"Run 'source ~/.zshrc' or open a new terminal for it to take effect."` — this will show as an approval prompt in Claude's next tool call, which the user accepts normally. |
Access to hidden dotfiles in home directory
| 2922 | ✓ Prefs: saved to ~/.claude/plugins/data/ops-ops-marketplace/preferences.json |
Access to hidden dotfiles in home directory
| 2950 | cat ~/.claude/plugins/data/ops-ops-marketplace/daemon-health.json |
Access to hidden dotfiles in home directory
| 2993 | - **Never** touch `~/.claude.json` or `~/.claude/settings.json` — MCP registration is Claude Code's job, not yours. |
Access to .env file
| 519 | **CRITICAL — exhaust ALL sources before reporting.** Run every scan source (1-10 below) in a single batch, THEN analyze the combined results. Do NOT report "no credentials found" after checking only e |
Access to .env file
| 546 | jq -r --arg var "$VAR" '.agents.defaults.env[$var] // empty' ~/.openclaw/openclaw.json 2>/dev/null |
Access to .env file
| 548 | 7. **Installed MCP configs** — read each `.mcp.json` the detector found. For each server entry, look at `.env` and `.args` for the variable name or for literal values that look like the target. Show t |
Access to .env file
| 556 | 10. **Project .env files** — scan `~/Projects/*/.env*` for the variable name or service domain patterns. These often contain credentials from other projects that can be reused. |
Access to .env file
| 605 | 2. All .env* files across ~/Projects/ recursively |
Access to .env file
| 669 | Also check `~/.claude.json mcpServers.telegram.env.TELEGRAM_API_ID`. If all 4 are found and the stored `TELEGRAM_SESSION` decodes as a StringSession, tell the user `"✓ Telegram already configured (api |
Access to .env file
| 748 | # Update .claude.json mcpServers.telegram.env with actual values |
Access to .env file
| 752 | '.mcpServers.telegram.env.TELEGRAM_API_ID = $id | .mcpServers.telegram.env.TELEGRAM_API_HASH = $hash | .mcpServers.telegram.env.TELEGRAM_PHONE = $phone | .mcpServers.telegram.env.TELEGRAM_SESSION = $s |
Access to .env file
| 1060 | - `~/.claude.json mcpServers.slack.env` (where Claude Code stores them) |
Access to .env file
| 1648 | jq -r '.agents.defaults.env | to_entries[] | select(.key | test("SHOPIFY")) | "\(.key)=\(.value)"' ~/.openclaw/openclaw.json 2>/dev/null |
Access to .env file
| 1662 | # Scan project .env files for store URLs |
Access to .env file
| 1663 | grep -rhE 'myshopify\.com|SHOPIFY_STORE' ~/Projects/*/.env* 2>/dev/null | grep -v '^#' | head -5 |
Access to .env file
| 1836 | jq -r '.agents.defaults.env | to_entries[] | select(.key | test("KLAVIYO|META_|FACEBOOK|GA4")) | "\(.key)=\(.value)"' ~/.openclaw/openclaw.json 2>/dev/null |
Access to .env file
| 2130 | jq -r '.agents.defaults.env | to_entries[] | select(.key | test("BLAND|ELEVENLABS|GROQ")) | "\(.key)=\(.value)"' ~/.openclaw/openclaw.json 2>/dev/null |
Access to .env file
| 2241 | jq -r '.agents.defaults.env | to_entries[] | select(.key | test("STRIPE|REVENUECAT")) | "\(.key)=\(.value)"' ~/.openclaw/openclaw.json 2>/dev/null |
Access to .env file
| 2272 | prompt: "Grep the filesystem under $HOME (excluding node_modules, .git, Library/Caches) for Stripe secret key patterns: sk_live_[A-Za-z0-9]+ and sk_test_[A-Za-z0-9]+. Also scan ~/.config, ~/.aws, ~/.d |
Access to .env file
| 2521 | prompt: "Grep the filesystem under $HOME (excluding node_modules, .git, Library/Caches) for Discord credentials. Patterns: bot tokens look like base64 segments separated by dots (e.g. MTAxXXXX.YYYYYY. |
Access to system keychain/keyring
| 29 | - Keychain writes, Doppler queries, Chrome history queries |
Access to system keychain/keyring
| 38 | Every Bash tool call MUST include a short `description` parameter (5-10 words, e.g. "Install missing CLIs", "Scout keychain for Telegram creds", "Reload daemon"). This is what the user sees instead of |
Access to system keychain/keyring
| 51 | - Run ALL diagnostic/probe commands in parallel when possible. Use multiple Bash tool calls in a single message. Never run sequential probes when they're independent (e.g., `gog auth status` AND `wacl |
Access to system keychain/keyring
| 64 | - Credential scouts run in parallel across Doppler, keychains, browser profiles, and password managers |
Access to system keychain/keyring
| 65 | - Agents share findings (e.g., Doppler agent finds a partial config → keychain agent knows to skip that service) |
Access to system keychain/keyring
| 444 | | Vault | vault | Password manager — 1Password, Dashlane, Bitwarden, or macOS Keychain | |
Access to system keychain/keyring
| 484 | For the authoritative cross-OS detection logic, reuse `bin/ops-setup-detect` (which emits `os`, `pkg_mgr`, `arch`, `keyring_backend`, `shell`, `browser_profiles_found` in its JSON output). |
Access to system keychain/keyring
| 519 | **CRITICAL — exhaust ALL sources before reporting.** Run every scan source (1-10 below) in a single batch, THEN analyze the combined results. Do NOT report "no credentials found" after checking only e |
Access to system keychain/keyring
| 539 | 5. **macOS Keychain** — for specific services: |
Access to system keychain/keyring
| 560 | | Variable names | Service keyword (Dashlane/Keychain) | |
Access to system keychain/keyring
| 606 | 3. macOS Keychain (security find-generic-password with various service name patterns) |
Access to system keychain/keyring
| 654 | 1. Scans scout sources (keychain → ~/.claude.json → shell profiles → Doppler) for previously-extracted `TELEGRAM_API_ID` / `TELEGRAM_API_HASH` / `TELEGRAM_SESSION`. |
Access to system keychain/keyring
| 661 | 1. **Scout first.** Check keychain for previously-extracted Telegram credentials: |
Access to system keychain/keyring
| 708 | 7. **Persist to keychain + preferences.** macOS only: |
Access to system keychain/keyring
| 717 | Then update `$PREFS_PATH` with `channels.telegram = {backend: "gram.js", api_id: "...", phone: "...", status: "configured"}`. **Never write the api_hash or session to preferences.json** — those stay i |
Access to system keychain/keyring
| 762 | Session: stored in keychain + MCP config |
Access to system keychain/keyring
| 1043 | Refresh tokens are stored in the OS keyring (Keychain on macOS, Secret Service / libsecret on Linux, Credential Manager on Windows). Then stop this sub-flow and wait for the user to re-run `/ops:setup |
Access to system keychain/keyring
| 1062 | - macOS keychain (`slack-xoxc`, `slack-xoxd`) |
Access to system keychain/keyring
| 1107 | - Keychain: `security add-generic-password -U -s slack-xoxc -a "$USER" -w "$XOXC"; security add-generic-password -U -s slack-xoxd -a "$USER" -w "$XOXD"`. |
Access to system keychain/keyring
| 1108 | - `$PREFS_PATH` → `channels.slack = {backend: "mcp:slack", team_id: "...", source: "...", status: "configured"}`. **Do not** store the raw tokens in preferences.json — keychain only. |
Access to system keychain/keyring
| 1113 | Slack tokens saved to keychain. To activate the MCP, Claude Code needs them |
Access to system keychain/keyring
| 1170 | 1. Scout keychain for existing Notion API key: |
Access to system keychain/keyring
| 1272 | Doppler is a secrets manager that injects environment variables at runtime. When configured, all ops skills can query secrets via `doppler secrets get` instead of reading from dotfiles or keychain. Th |
Access to system keychain/keyring
| 1443 | security find-generic-password -s "test" 2>&1 | head -1 # macOS Keychain (always available) |
Access to system keychain/keyring
| 1446 | Parse each result to classify as `authenticated`, `needs_unlock`, `not_installed`, or `available` (Keychain is always `available`). |
Access to system keychain/keyring
| 1450 | Show only what was detected via `AskUserQuestion`. **Max 4 options per call.** Since macOS Keychain and Skip are always shown, you have room for at most 2 detected managers per call. If all 3 CLIs (1P |
Access to system keychain/keyring
| 1457 | [macOS Keychain — always available] |
Access to system keychain/keyring
| 1471 | [macOS Keychain — always available] |
Access to system keychain/keyring
| 1475 | Never show managers that aren't installed. Always show macOS Keychain and Skip. If none of the CLIs are installed, skip straight to showing just `[macOS Keychain — always available]` and `[Skip]`. |
Access to system keychain/keyring
| 1535 | **macOS Keychain:** |
Access to system keychain/keyring
| 1540 | macOS Keychain is always available but is limited to items stored locally. |
Access to system keychain/keyring
| 1555 | "password_manager": "<1password|dashlane|bitwarden|keychain>", |
Access to system keychain/keyring
| 1588 | security find-generic-password -s "my-project-db" -w (Keychain example) |
Access to system keychain/keyring
| 1615 | > **Deep-dive:** no dedicated skill ships with the password manager integration — see `${CLAUDE_PLUGIN_ROOT}/docs/memories-system.md` (Runtime Context section) for how downstream skills resolve `passw |
Access to system keychain/keyring
| 1643 | # Scan macOS Keychain |
Access to system keychain/keyring
| 2236 | # macOS Keychain |
Access to system keychain/keyring
| 2491 | # macOS Keychain (Darwin only — the setup wizard already guards this at the OS level) |
Access to system keychain/keyring
| 2581 | Mirror the webhook to the flat `discord_webhook_url` key so `scripts/ops-notify.sh` (the existing fires sink) continues to find it. Prefer a Doppler reference over raw tokens when Doppler is configure |
Access to system keychain/keyring
| 2655 | The script reads Shopify creds from `$PREFS_PATH .ecom.shopify.*` + `SHOPIFY_*` env, Linear from `LINEAR_API_KEY`, Slack from keychain `slack-xoxc`/`slack-xoxd`, and Notion from `NOTION_API_KEY` / key |
Access to system keychain/keyring
| 3115 | ### macOS Keychain |
External URL reference
| 231 | Report success/failure. If Homebrew is missing on macOS, stop and tell the user to install it from https://brew.sh first — do not attempt to install brew automatically. |
External URL reference
| 1036 | Docs: <https://gogcli.sh/> · Repo: <https://github.com/steipete/gogcli> |
External URL reference
| 1065 | 2. **Phase 2 — Playwright extraction** — only if nothing is found, launches a persistent-profile Chromium, opens `https://app.slack.com/client/`, asks the user to log in (or uses an existing session f |
External URL reference
| 1088 | --workspace "https://app.slack.com/client/" \ |
External URL reference
| 1102 | curl -s -H "Authorization: Bearer XOXC_TOKEN" -b "d=XOXD_TOKEN" "https://slack.com/api/auth.test" |
External URL reference
| 1104 | Expect `{"ok":true, "team_id":"T...", "user_id":"U...", "url":"https://<workspace>.slack.com/"}`. If `ok:false`, show the error and re-ask. |
External URL reference
| 1123 | 8. **Smoke test**: call `https://slack.com/api/conversations.list?limit=1` with the tokens. Expect `ok:true` with at least one channel in the response. |
External URL reference
| 1178 | Create one at https://www.notion.so/my-integrations |
External URL reference
| 1194 | curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $NOTION_API_KEY" -H "Notion-Version: 2022-06-28" https://api.notion.com/v1/users/me | grep -q "200" && echo "OK" || echo "FAIL" |
External URL reference
| 1293 | | Debian / Ubuntu | `curl -Ls https://cli.doppler.com/install.sh \| sudo sh` | |
External URL reference
| 1294 | | Fedora / RHEL | `sudo rpm --import https://packages.doppler.com/public.key && sudo dnf install -y doppler` | |
External URL reference
| 1684 | Validate the input: strip `https://`, strip trailing slash, check that the result ends with `.myshopify.com`. If invalid, ask again with a correction note. |
External URL reference
| 1705 | 3. **Browser automation** — if Kapture/Playwright MCP is available, navigate to `https://admin.shopify.com/store/<slug>/settings/apps/development` and automate the "Create an app" → "Configure scopes" |
External URL reference
| 1710 | 1. Go to https://admin.shopify.com/store/<slug>/settings/apps/development |
External URL reference
| 1732 | "https://$STORE/admin/api/2024-10/shop.json" | jq '.shop.name' |
External URL reference
| 1775 | "api_base_url": "https://api.shipbob.com/v1", |
External URL reference
| 1798 | | ShipBob | `Authorization: Bearer <token>` | `https://api.shipbob.com/v1` | `/user` | |
External URL reference
| 1799 | | Recharge | `X-Recharge-Access-Token: <token>` | `https://api.rechargeapps.com/v1` | `/shop` | |
External URL reference
| 1800 | | Yotpo | `X-Api-Key: <app_key>` | `https://api.yotpo.com` | `/core/v3/stores/<id>` | |
External URL reference
| 1801 | | Shippo | `Authorization: ShippoToken <token>` | `https://api.goshippo.com` | `/carrier_accounts` | |
External URL reference
| 1802 | | Gorgias | `Authorization: Basic <base64>` | `https://<domain>.gorgias.com/api` | `/account` | |
External URL reference
| 1803 | | Loop | `X-Authorization: <secret>` | `https://api.loopreturns.com/api/v1` | `/warehouse` | |
External URL reference
| 1804 | | Attentive | `Authorization: Bearer <token>` | `https://api.attentivemobile.com/v1` | `/me` | |
External URL reference
| 1876 | "https://a.klaviyo.com/api/lists" | jq '.data | length' |
External URL reference
| 1890 | curl -s "https://graph.facebook.com/v20.0/$AD_ACCOUNT_ID/campaigns?access_token=$TOKEN&limit=1" | jq '.data | length' |
External URL reference
| 1901 | > Note: New developer tokens start in "test" mode — they work against test accounts only. For production data, apply for Basic Access at https://ads.google.com/home/tools/manager-accounts/ |
External URL reference
| 1914 | AUTH_URL="https://accounts.google.com/o/oauth2/auth?client_id=${GADS_CLIENT_ID}&redirect_uri=http://localhost:8080&response_type=code&scope=https://www.googleapis.com/auth/adwords&access_type=offline& |
External URL reference
| 1921 | node -e "require('http').createServer((req,res)=>{const code=new URL(req.url,'http://localhost').searchParams.get('code');if(code){res.end('Authorization code received. You can close this tab.');proce |
External URL reference
| 1930 | TOKEN_RESP=$(curl -s -X POST https://oauth2.googleapis.com/token \ |
External URL reference
| 1934 | --data "redirect_uri=http://localhost:8080" \ |
External URL reference
| 1946 | ACCESS_TOKEN=$(curl -s -X POST https://oauth2.googleapis.com/token \ |
External URL reference
| 1950 | "https://googleads.googleapis.com/v23/customers:listAccessibleCustomers" \ |
External URL reference
| 1961 | curl -s -X GET "https://googleads.googleapis.com/v23/customers:listAccessibleCustomers" \ |
External URL reference
| 1999 | Ask for the site URL (format: `https://example.com/` or `sc-domain:example.com`). No API key needed if gcloud is authed. |
External URL reference
| 2005 | "https://searchconsole.googleapis.com/webmasters/v3/sites" | jq '.siteEntry | length' |
External URL reference
| 2034 | curl -s "https://graph.facebook.com/v20.0/${WABA_PHONE_ID}" \ |
External URL reference
| 2049 | "gsc": { "site_url": "https://example.com/" }, |
External URL reference
| 2078 | "api_base_url": "https://api.triplewhale.com/api/v2", |
External URL reference
| 2094 | | HubSpot | `Authorization: Bearer <token>` | `https://api.hubapi.com` | `/crm/v3/objects/contacts?limit=1` | |
External URL reference
| 2095 | | Mailchimp | `Authorization: Bearer <api_key>` | `https://<dc>.api.mailchimp.com/3.0` | `/ping` | |
External URL reference
| 2096 | | Segment | `Authorization: Basic <base64_key:>` | `https://api.segment.io/v1` | n/a — use write key | |
External URL reference
| 2097 | | Mixpanel | `Authorization: Basic <base64_secret:>` | `https://data.mixpanel.com/api/2.0` | `/engage?limit=1` | |
External URL reference
| 2098 | | Postscript | `Authorization: ApiKey <key>` | `https://api.postscript.io/api/v2` | `/shops` | |
External URL reference
| 2099 | | Triple Whale | `Authorization: Bearer <token>` | `https://api.triplewhale.com/api/v2` | `/attribution/get-attribution-data` | |
External URL reference
| 2148 | To find it: https://app.bland.ai → Settings → API Key |
External URL reference
| 2153 | curl -s -H "Authorization: $KEY" "https://api.bland.ai/v1/me" | jq '.user.id' |
External URL reference
| 2162 | To find it: https://elevenlabs.io → Profile (top-right) → API Key |
External URL reference
| 2167 | curl -s -H "xi-api-key: $KEY" "https://api.elevenlabs.io/v1/user" | jq '.subscription.tier' |
External URL reference
| 2176 | To generate one: https://console.groq.com → API Keys → Create API Key |
External URL reference
| 2183 | "https://api.groq.com/openai/v1/models" | jq '.data | length' |
External URL reference
| 2288 | curl -s -u "$STRIPE_SECRET_KEY:" "https://api.stripe.com/v1/balance" | jq '.available | length' |
External URL reference
| 2328 | "https://api.revenuecat.com/v2/projects/$REVENUECAT_PROJECT_ID/metrics/overview" | jq '.metrics // .object' |
External URL reference
| 2412 | Show the topic and install instructions (`open https://ntfy.sh/<topic>` in a browser, or scan the QR in the ntfy mobile app). Save to `$PREFS_PATH` under `ntfy_topic`. |
External URL reference
| 2417 | curl -s -X POST https://api.pushover.net/1/messages.json \ |
External URL reference
| 2426 | **Discord** — if the user already set `discord_default_webhook_url` via a prior run (or issue #20's work), reuse it; otherwise Rule-3-prompt for a webhook URL (`https://discord.com/api/webhooks/...`). |
External URL reference
| 2521 | prompt: "Grep the filesystem under $HOME (excluding node_modules, .git, Library/Caches) for Discord credentials. Patterns: bot tokens look like base64 segments separated by dots (e.g. MTAxXXXX.YYYYYY. |
External URL reference
| 2531 | Find it: https://discord.com/developers/applications → your app → Bot → Reset Token |
External URL reference
| 2542 | curl -sS "https://discord.com/api/v10/users/@me" \ |
External URL reference
| 2554 | Format: https://discord.com/api/webhooks/<ID>/<TOKEN> |
External URL reference
| 3112 | curl -s -H "Authorization: Bearer XOXC_TOKEN" -b "d=XOXD_TOKEN" "https://slack.com/api/auth.test" |