[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71HB6C8PY9CS3KVWAW7ZHNN":3,"skill-same:01M71HB6C8PY9CS3KVWAW7ZHNN":111},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":25,"publishedAt":45,"linkOnly":46,"markdownContent":47,"markdownBody":48,"frontMatter":49,"refName":50,"commitSha":51,"skillDirectory":52,"forksCount":53,"repositoryHtmlUrl":54,"repositoryHomepageUrl":6,"ownerHtmlUrl":55,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":56,"install":57,"resources":70},"01M71HB6C8PY9CS3KVWAW7ZHNN","slack",null,"Interact with Slack via the Web API. Read, summarize, search, post messages, react, pin, and manage channels. Use when the user (1) shares a Slack URL, (2) asks to read or summarize a channel, (3) searches Slack messages, (4) asks to send\u002Fpost a message, (5) asks to react to or pin a message, (6) looks up a user, or (7) mentions a Slack channel by name (e.g., \"#channel-name\"). Also triggers for Slack threads, daily standups, conversation digests, or any Slack interaction.","JSGforever\u002Fskillguard","JSGforever","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F85541948?v=4","01M71FQD3E132VMR5F4TAYX3YS","01M71FQD4DYW0XJ4XQ4YQH75Y9",2,"GPL-3.0","https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__azmym--slack\u002FSKILL.md",[17,22],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000005","邮件与沟通","SCENARIO","使用场景",{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000010","后端与接口",[5,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44],"manage","slack messages","up","messages","manage channels","user","name","post","use","triggers","for","web api","read","interaction","react","URL","send","search","conversation","2026-11-10 10:12:30",false,"---\nname: slack\ndescription: Interact with Slack via the Web API. Read, summarize, search, post messages, react, pin, and manage channels. Use when the user (1) shares a Slack URL, (2) asks to read or summarize a channel, (3) searches Slack messages, (4) asks to send\u002Fpost a message, (5) asks to react to or pin a message, (6) looks up a user, or (7) mentions a Slack channel by name (e.g., \"#channel-name\"). Also triggers for Slack threads, daily standups, conversation digests, or any Slack interaction.\n---\n\n# Slack Web API Skill\n\nInteract with Slack: read, write, search, react, pin, and manage conversations via the Web API.\n\n## IMPORTANT: First-Use Initialization\n\n**Before executing any Slack operation**, check if the mode config file exists:\n\n    cat ~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env\n\nIf the file does **not** exist (or does not contain `SLACK_MODE`), you **must** ask the user which mode they want to use. Present these three options:\n\n1. **Token** (macOS only): Extracts session tokens directly from Chrome. Fastest option. Requires Chrome with Slack open, AppleScript enabled, and `uvx` installed.\n2. **Browser** (cross-platform): Uses a local Playwright browser to make API calls. Works on macOS, Linux, and Windows. Requires Node.js 18+. Supports SSO and 2FA login.\n3. **Auto-detect** (recommended): Automatically uses browser mode if a Playwright session exists, otherwise falls back to token mode. Best of both worlds.\n\nOnce the user selects a mode, save it immediately:\n\n    mkdir -p ~\u002F.agents\u002Fconfig\u002Fslack\n    echo 'SLACK_MODE=\u003Cselected_value>' > ~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env\n\nWhere `\u003Cselected_value>` is `token`, `browser`, or `auto`.\n\n**After saving, never ask again.** On all subsequent invocations, the config file will exist and the skill will use the saved mode automatically.\n\nIf the user selected `browser` mode, also run the browser session setup:\n\n    {SKILL_DIR}\u002Fscripts\u002Fslack-browser-session.sh login-manual\n\nThis opens a visible browser for the user to log in to Slack (supports SSO\u002F2FA). The session is saved and reused for all future API calls.\n\n---\n\n## Mode Selection\n\nThe skill supports three modes. Set via `~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env` or the `SLACK_MODE` environment variable:\n\n| Mode | Value | Behavior |\n|------|-------|----------|\n| Token | `token` | Direct curl calls using Chrome session tokens. Fast. macOS only. |\n| Browser | `browser` | API calls through a local Playwright browser session. Cross-platform. |\n| Auto-detect | `auto` | Use browser if session exists; falls back to token on auth failure. **(default)** |\n\n### Configure the mode\n\nOption 1: Config file (persistent)\n\n    echo 'SLACK_MODE=token' > ~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env\n    # or\n    echo 'SLACK_MODE=browser' > ~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env\n    # or\n    echo 'SLACK_MODE=auto' > ~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env\n\nOption 2: Environment variable (per-call override)\n\n    SLACK_MODE=browser slack-api.sh conversations.history channel=C041RSY6DN2 limit=20\n\nThe environment variable takes priority over the config file.\n\n## Config and State Directory\n\nAll skill config and state lives under `~\u002F.agents\u002Fconfig\u002Fslack\u002F`:\n\n| File | Purpose |\n|------|----------|\n| `config.env` | Mode selection (`SLACK_MODE=auto\\|token\\|browser`) |\n| `tokens.env` | Cached session tokens (xoxc, xoxd, user-agent) |\n| `browser-session` | Active browser session ID |\n| `sessions\u002F\u003Cid>\u002FstorageState.json` | Playwright session cookies and localStorage |\n\nThis directory is created automatically on first use.\n\n## API Wrapper\n\nAll calls go through a single unified script:\n\n    {SKILL_DIR}\u002Fscripts\u002Fslack-api.sh \u003Cmethod> [key=value ...]\n\nWhere `{SKILL_DIR}` is the base directory provided when this skill is loaded (e.g., `~\u002F.agents\u002Fskills\u002Fslack`).\n\nThe script automatically routes to the correct mode based on your configuration. For the full method reference, see [references\u002Fapi-methods.md](references\u002Fapi-methods.md).\n\n## Token Mode (macOS)\n\nToken mode extracts session tokens from your running Chrome browser and makes direct curl calls to the Slack Web API.\n\nPrerequisites:\n- Chrome running with Slack open at app.slack.com\n- Chrome > View > Developer > Allow JavaScript from Apple Events\n- `uvx` installed (`brew install uv`)\n\nNo manual setup needed. On first API call, tokens are extracted automatically.\n\n## Browser Mode (Cross-Platform)\n\nBrowser mode uses a local Playwright Chromium instance to maintain a Slack session. API calls are made via `fetch()` inside the browser context, so no token extraction is needed. This works on macOS, Linux, and Windows.\n\nPrerequisites:\n- Node.js 18+ installed\n- Playwright auto-installs on first use (downloads Chromium, ~150 MB)\n\nFor detailed documentation, see [references\u002Fbrowser-mode.md](references\u002Fbrowser-mode.md).\n\n### Quick Start (Browser Mode)\n\n    # 1. Set mode to browser\n    echo 'SLACK_MODE=browser' > ~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env\n\n    # 2. Start a browser session and log in manually (supports SSO\u002F2FA)\n    {SKILL_DIR}\u002Fscripts\u002Fslack-browser-session.sh login-manual\n\n    # Or: automated email+password login\n    {SKILL_DIR}\u002Fscripts\u002Fslack-browser-session.sh start\n    {SKILL_DIR}\u002Fscripts\u002Fslack-browser-session.sh login user@example.com mypassword\n\n    # 3. Verify login succeeded\n    {SKILL_DIR}\u002Fscripts\u002Fslack-browser-session.sh status\n\n    # 4. Make API calls (same script, routes through browser automatically)\n    {SKILL_DIR}\u002Fscripts\u002Fslack-api.sh conversations.history channel=C041RSY6DN2 limit=20\n\n    # 5. Close when done\n    {SKILL_DIR}\u002Fscripts\u002Fslack-browser-session.sh stop\n\n### UI Automation (API Gaps)\n\nBrowser mode also enables direct interaction with Slack's web UI for features that lack API support:\n\n    # Get the session ID\n    SESSION_ID=$({SKILL_DIR}\u002Fscripts\u002Fslack-browser-session.sh get)\n\n    # Navigate to a specific channel\n    node {SKILL_DIR}\u002Fscripts\u002Fplaywright-bridge.js --function interact --session $SESSION_ID \\\n      --input '{\"action\": \"goto\", \"url\": \"https:\u002F\u002Fapp.slack.com\u002Fclient\u002FTEAM_ID\u002FCHANNEL_ID\"}'\n\n    # Take a snapshot to see interactive elements\n    node {SKILL_DIR}\u002Fscripts\u002Fplaywright-bridge.js --function snapshot --session $SESSION_ID --input '{}'\n\n    # Interact with UI elements using @e refs from the snapshot\n    node {SKILL_DIR}\u002Fscripts\u002Fplaywright-bridge.js --function interact --session $SESSION_ID \\\n      --input '{\"action\": \"click\", \"ref\": \"@e5\"}'\n\n    # Take a screenshot for visual verification\n    node {SKILL_DIR}\u002Fscripts\u002Fplaywright-bridge.js --function screenshot --session $SESSION_ID --input '{}'\n\nUse cases for UI automation:\n\n- Canvas creation and editing (no public API)\n- Huddle interactions (no API)\n- Workflow Builder configuration\n- Slack Connect invitations\n- Admin and settings pages\n- Visual message verification via screenshots\n\n## Parsing Slack URLs\n\nExtract channel and timestamp from Slack URLs:\n\n    https:\u002F\u002F{WORKSPACE}.slack.com\u002Farchives\u002F{CHANNEL_ID}\u002Fp{TIMESTAMP_WITHOUT_DOT}\n\nInsert a dot before the last 6 digits of the timestamp:\n- URL: p1770725748342899 -> ts: 1770725748.342899\n\nFor threaded messages, the URL may include ?thread_ts= parameter.\n\n## Read Operations\n\n### Read a thread\n\n    slack-api.sh conversations.replies channel=CHANNEL_ID ts=THREAD_TS limit=100\n\n### Read channel history\n\n    slack-api.sh conversations.history channel=CHANNEL_ID limit=20\n\nOptional: `oldest` \u002F `latest` (Unix timestamps) to bound the time range.\n\n### Search messages\n\n    slack-api.sh search.messages query=\"search terms\" count=10\n\nModifiers: `in:#channel`, `from:@user`, `before:YYYY-MM-DD`, `after:YYYY-MM-DD`, `has:link`, `has:reaction`, `has:pin`.\n\n### Find a channel by name\n\n    slack-api.sh conversations.list types=public_channel limit=200 | python3 -c \"import sys,json; channels=json.load(sys.stdin).get('channels',[]); matches=[c for c in channels if 'TARGET' in c['name']]; [print(f\\\"{c['id']} #{c['name']}\\\") for c in matches]\"\n\n### Look up a user\n\n    slack-api.sh users.info user=USER_ID\n\nName: `.user.real_name` or `.user.profile.display_name`.\n\n### List pinned items\n\n    slack-api.sh pins.list channel=CHANNEL_ID\n\n### List channel members\n\n    slack-api.sh conversations.members channel=CHANNEL_ID limit=100\n\n## Write Operations\n\n**IMPORTANT: Confirmation required before any write operation.**\n\nBefore sending, editing, deleting a message, adding\u002Fremoving reactions, or pinning\u002Funpinning, always show the user a preview and ask for confirmation. Format the preview as:\n\n> **To:** #channel-name (or @username for DMs)\n> **Message:** The exact message text\n> **Action:** Send \u002F Edit \u002F Delete \u002F React \u002F Pin (as applicable)\n>\n> Send this? (or: want to change anything?)\n\nDo NOT execute the write API call until the user explicitly confirms. If the user wants changes, update the preview and ask again.\n\n### Send a message\n\n    slack-api.sh chat.postMessage channel=CHANNEL_ID text=\"Hello world\"\n\nThread reply: add `thread_ts=PARENT_TS`. Broadcast to channel: add `reply_broadcast=true`.\n\n### Edit a message\n\n    slack-api.sh chat.update channel=CHANNEL_ID ts=MESSAGE_TS text=\"Updated text\"\n\n### Delete a message\n\n    slack-api.sh chat.delete channel=CHANNEL_ID ts=MESSAGE_TS\n\n### Add a reaction\n\n    slack-api.sh reactions.add channel=CHANNEL_ID timestamp=MESSAGE_TS name=thumbsup\n\nEmoji name without colons. Supports skin tones: `thumbsup::skin-tone-3`.\n\n### Remove a reaction\n\n    slack-api.sh reactions.remove channel=CHANNEL_ID timestamp=MESSAGE_TS name=thumbsup\n\n### Pin a message\n\n    slack-api.sh pins.add channel=CHANNEL_ID timestamp=MESSAGE_TS\n\n### Unpin a message\n\n    slack-api.sh pins.remove channel=CHANNEL_ID timestamp=MESSAGE_TS\n\n## Image and File Handling\n\nMessages may contain files. In token mode:\n\n    source ~\u002F.agents\u002Fconfig\u002Fslack\u002Ftokens.env\n    curl -s \"FILE_URL_PRIVATE\" \\\n      -H \"Authorization: Bearer ${SLACK_XOXC}\" \\\n      -H \"Cookie: d=${SLACK_XOXD}\" \\\n      -o \u002Ftmp\u002Fslack-image-N.png\n\nIn browser mode, navigate to the file URL and screenshot:\n\n    node {SKILL_DIR}\u002Fscripts\u002Fplaywright-bridge.js --function interact --session $SESSION_ID \\\n      --input '{\"action\": \"goto\", \"url\": \"FILE_URL_PRIVATE\"}'\n    node {SKILL_DIR}\u002Fscripts\u002Fplaywright-bridge.js --function screenshot --session $SESSION_ID --input '{}'\n\nThen use the Read tool to view the downloaded image.\n\n## Output Formatting\n\n1. Parse JSON with python3 -c \"import sys,json; ...\"\n2. Resolve user IDs (U...) to real names via users.info (cache lookups)\n3. Present messages with timestamps and names\n4. Replace \u003C@U...> mentions with resolved real names\n5. Decode Slack markup (entities, link syntax, channel references) to plain text\n\n## Rate Limiting\n\n- Add sleep 1 between consecutive API calls\n- Never bulk-paginate large datasets (users.list), it kills the session\n- Prefer targeted queries over bulk fetches\n- Browser mode has additional latency per call; batch where possible\n\n## Token Refresh (Token Mode, Automatic)\n\nToken refresh is fully automatic. The API wrapper:\n1. Auto-refreshes if `~\u002F.agents\u002Fconfig\u002Fslack\u002Ftokens.env` is missing\n2. Auto-refreshes on `invalid_auth` errors and retries the call\n\nTokens are extracted from the running Chrome browser:\n- xoxc: from Slack's localStorage via AppleScript\n- xoxd: from Chrome's cookie database via `lsof` + `pycookiecheat`\n\n## Setup\n\n### Token Mode (macOS)\n\n1. Open Chrome with Slack at app.slack.com\n2. Enable Chrome > View > Developer > Allow JavaScript from Apple Events\n3. Install uv: `brew install uv`\n4. Set mode (optional, auto-detect works by default):\n\n       echo 'SLACK_MODE=token' > ~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env\n\n### Browser Mode (Cross-Platform)\n\n1. Install Node.js 18+ from https:\u002F\u002Fnodejs.org\n2. Set mode and start a session:\n\n       echo 'SLACK_MODE=browser' > ~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env\n       {SKILL_DIR}\u002Fscripts\u002Fslack-browser-session.sh login-manual\n\n   Playwright and Chromium install automatically on first use.\n\n### Auto-detect (Default)\n\nNo configuration needed. The skill checks for an active browser session first and makes the API call via Playwright. If the browser call returns an auth error (`invalid_auth`, `not_authed`, or `no_teams_found`), it automatically falls back to token mode. This provides seamless recovery when a browser session expires.\n\n## Full API Reference\n\nFor additional methods (bookmarks, user groups, reminders, emoji, files, user profiles, etc.), see [references\u002Fapi-methods.md](references\u002Fapi-methods.md).\n\n## Error Handling\n\n- not_in_channel: User does not have access to this channel\n- channel_not_found: Invalid channel ID\n- invalid_auth: Token expired, auto-refresh attempted (token mode)\n- ratelimited: Wait and retry with sleep 5\n- cant_update_message \u002F cant_delete_message: Can only modify own messages\n- no_browser_session: No active browser session; run slack-browser-session.sh start\n- node_not_found: Node.js not installed; install from https:\u002F\u002Fnodejs.org\n- no_teams_found: Slack has not loaded workspace data in browser; wait and retry\n- **Automatic fallback**: In auto mode, if the browser call returns `invalid_auth`, `not_authed`, or `no_teams_found`, the skill automatically retries via token mode. No manual intervention needed.\n","# Slack Web API Skill\n\nInteract with Slack: read, write, search, react, pin, and manage conversations via the Web API.\n\n## IMPORTANT: First-Use Initialization\n\n**Before executing any Slack operation**, check if the mode config file exists:\n\n    cat ~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env\n\nIf the file does **not** exist (or does not contain `SLACK_MODE`), you **must** ask the user which mode they want to use. Present these three options:\n\n1. **Token** (macOS only): Extracts session tokens directly from Chrome. Fastest option. Requires Chrome with Slack open, AppleScript enabled, and `uvx` installed.\n2. **Browser** (cross-platform): Uses a local Playwright browser to make API calls. Works on macOS, Linux, and Windows. Requires Node.js 18+. Supports SSO and 2FA login.\n3. **Auto-detect** (recommended): Automatically uses browser mode if a Playwright session exists, otherwise falls back to token mode. Best of both worlds.\n\nOnce the user selects a mode, save it immediately:\n\n    mkdir -p ~\u002F.agents\u002Fconfig\u002Fslack\n    echo 'SLACK_MODE=\u003Cselected_value>' > ~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env\n\nWhere `\u003Cselected_value>` is `token`, `browser`, or `auto`.\n\n**After saving, never ask again.** On all subsequent invocations, the config file will exist and the skill will use the saved mode automatically.\n\nIf the user selected `browser` mode, also run the browser session setup:\n\n    {SKILL_DIR}\u002Fscripts\u002Fslack-browser-session.sh login-manual\n\nThis opens a visible browser for the user to log in to Slack (supports SSO\u002F2FA). The session is saved and reused for all future API calls.\n\n---\n\n## Mode Selection\n\nThe skill supports three modes. Set via `~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env` or the `SLACK_MODE` environment variable:\n\n| Mode | Value | Behavior |\n|------|-------|----------|\n| Token | `token` | Direct curl calls using Chrome session tokens. Fast. macOS only. |\n| Browser | `browser` | API calls through a local Playwright browser session. Cross-platform. |\n| Auto-detect | `auto` | Use browser if session exists; falls back to token on auth failure. **(default)** |\n\n### Configure the mode\n\nOption 1: Config file (persistent)\n\n    echo 'SLACK_MODE=token' > ~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env\n    # or\n    echo 'SLACK_MODE=browser' > ~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env\n    # or\n    echo 'SLACK_MODE=auto' > ~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env\n\nOption 2: Environment variable (per-call override)\n\n    SLACK_MODE=browser slack-api.sh conversations.history channel=C041RSY6DN2 limit=20\n\nThe environment variable takes priority over the config file.\n\n## Config and State Directory\n\nAll skill config and state lives under `~\u002F.agents\u002Fconfig\u002Fslack\u002F`:\n\n| File | Purpose |\n|------|----------|\n| `config.env` | Mode selection (`SLACK_MODE=auto\\|token\\|browser`) |\n| `tokens.env` | Cached session tokens (xoxc, xoxd, user-agent) |\n| `browser-session` | Active browser session ID |\n| `sessions\u002F\u003Cid>\u002FstorageState.json` | Playwright session cookies and localStorage |\n\nThis directory is created automatically on first use.\n\n## API Wrapper\n\nAll calls go through a single unified script:\n\n    {SKILL_DIR}\u002Fscripts\u002Fslack-api.sh \u003Cmethod> [key=value ...]\n\nWhere `{SKILL_DIR}` is the base directory provided when this skill is loaded (e.g., `~\u002F.agents\u002Fskills\u002Fslack`).\n\nThe script automatically routes to the correct mode based on your configuration. For the full method reference, see [references\u002Fapi-methods.md](references\u002Fapi-methods.md).\n\n## Token Mode (macOS)\n\nToken mode extracts session tokens from your running Chrome browser and makes direct curl calls to the Slack Web API.\n\nPrerequisites:\n- Chrome running with Slack open at app.slack.com\n- Chrome > View > Developer > Allow JavaScript from Apple Events\n- `uvx` installed (`brew install uv`)\n\nNo manual setup needed. On first API call, tokens are extracted automatically.\n\n## Browser Mode (Cross-Platform)\n\nBrowser mode uses a local Playwright Chromium instance to maintain a Slack session. API calls are made via `fetch()` inside the browser context, so no token extraction is needed. This works on macOS, Linux, and Windows.\n\nPrerequisites:\n- Node.js 18+ installed\n- Playwright auto-installs on first use (downloads Chromium, ~150 MB)\n\nFor detailed documentation, see [references\u002Fbrowser-mode.md](references\u002Fbrowser-mode.md).\n\n### Quick Start (Browser Mode)\n\n    # 1. Set mode to browser\n    echo 'SLACK_MODE=browser' > ~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env\n\n    # 2. Start a browser session and log in manually (supports SSO\u002F2FA)\n    {SKILL_DIR}\u002Fscripts\u002Fslack-browser-session.sh login-manual\n\n    # Or: automated email+password login\n    {SKILL_DIR}\u002Fscripts\u002Fslack-browser-session.sh start\n    {SKILL_DIR}\u002Fscripts\u002Fslack-browser-session.sh login user@example.com mypassword\n\n    # 3. Verify login succeeded\n    {SKILL_DIR}\u002Fscripts\u002Fslack-browser-session.sh status\n\n    # 4. Make API calls (same script, routes through browser automatically)\n    {SKILL_DIR}\u002Fscripts\u002Fslack-api.sh conversations.history channel=C041RSY6DN2 limit=20\n\n    # 5. Close when done\n    {SKILL_DIR}\u002Fscripts\u002Fslack-browser-session.sh stop\n\n### UI Automation (API Gaps)\n\nBrowser mode also enables direct interaction with Slack's web UI for features that lack API support:\n\n    # Get the session ID\n    SESSION_ID=$({SKILL_DIR}\u002Fscripts\u002Fslack-browser-session.sh get)\n\n    # Navigate to a specific channel\n    node {SKILL_DIR}\u002Fscripts\u002Fplaywright-bridge.js --function interact --session $SESSION_ID \\\n      --input '{\"action\": \"goto\", \"url\": \"https:\u002F\u002Fapp.slack.com\u002Fclient\u002FTEAM_ID\u002FCHANNEL_ID\"}'\n\n    # Take a snapshot to see interactive elements\n    node {SKILL_DIR}\u002Fscripts\u002Fplaywright-bridge.js --function snapshot --session $SESSION_ID --input '{}'\n\n    # Interact with UI elements using @e refs from the snapshot\n    node {SKILL_DIR}\u002Fscripts\u002Fplaywright-bridge.js --function interact --session $SESSION_ID \\\n      --input '{\"action\": \"click\", \"ref\": \"@e5\"}'\n\n    # Take a screenshot for visual verification\n    node {SKILL_DIR}\u002Fscripts\u002Fplaywright-bridge.js --function screenshot --session $SESSION_ID --input '{}'\n\nUse cases for UI automation:\n\n- Canvas creation and editing (no public API)\n- Huddle interactions (no API)\n- Workflow Builder configuration\n- Slack Connect invitations\n- Admin and settings pages\n- Visual message verification via screenshots\n\n## Parsing Slack URLs\n\nExtract channel and timestamp from Slack URLs:\n\n    https:\u002F\u002F{WORKSPACE}.slack.com\u002Farchives\u002F{CHANNEL_ID}\u002Fp{TIMESTAMP_WITHOUT_DOT}\n\nInsert a dot before the last 6 digits of the timestamp:\n- URL: p1770725748342899 -> ts: 1770725748.342899\n\nFor threaded messages, the URL may include ?thread_ts= parameter.\n\n## Read Operations\n\n### Read a thread\n\n    slack-api.sh conversations.replies channel=CHANNEL_ID ts=THREAD_TS limit=100\n\n### Read channel history\n\n    slack-api.sh conversations.history channel=CHANNEL_ID limit=20\n\nOptional: `oldest` \u002F `latest` (Unix timestamps) to bound the time range.\n\n### Search messages\n\n    slack-api.sh search.messages query=\"search terms\" count=10\n\nModifiers: `in:#channel`, `from:@user`, `before:YYYY-MM-DD`, `after:YYYY-MM-DD`, `has:link`, `has:reaction`, `has:pin`.\n\n### Find a channel by name\n\n    slack-api.sh conversations.list types=public_channel limit=200 | python3 -c \"import sys,json; channels=json.load(sys.stdin).get('channels',[]); matches=[c for c in channels if 'TARGET' in c['name']]; [print(f\\\"{c['id']} #{c['name']}\\\") for c in matches]\"\n\n### Look up a user\n\n    slack-api.sh users.info user=USER_ID\n\nName: `.user.real_name` or `.user.profile.display_name`.\n\n### List pinned items\n\n    slack-api.sh pins.list channel=CHANNEL_ID\n\n### List channel members\n\n    slack-api.sh conversations.members channel=CHANNEL_ID limit=100\n\n## Write Operations\n\n**IMPORTANT: Confirmation required before any write operation.**\n\nBefore sending, editing, deleting a message, adding\u002Fremoving reactions, or pinning\u002Funpinning, always show the user a preview and ask for confirmation. Format the preview as:\n\n> **To:** #channel-name (or @username for DMs)\n> **Message:** The exact message text\n> **Action:** Send \u002F Edit \u002F Delete \u002F React \u002F Pin (as applicable)\n>\n> Send this? (or: want to change anything?)\n\nDo NOT execute the write API call until the user explicitly confirms. If the user wants changes, update the preview and ask again.\n\n### Send a message\n\n    slack-api.sh chat.postMessage channel=CHANNEL_ID text=\"Hello world\"\n\nThread reply: add `thread_ts=PARENT_TS`. Broadcast to channel: add `reply_broadcast=true`.\n\n### Edit a message\n\n    slack-api.sh chat.update channel=CHANNEL_ID ts=MESSAGE_TS text=\"Updated text\"\n\n### Delete a message\n\n    slack-api.sh chat.delete channel=CHANNEL_ID ts=MESSAGE_TS\n\n### Add a reaction\n\n    slack-api.sh reactions.add channel=CHANNEL_ID timestamp=MESSAGE_TS name=thumbsup\n\nEmoji name without colons. Supports skin tones: `thumbsup::skin-tone-3`.\n\n### Remove a reaction\n\n    slack-api.sh reactions.remove channel=CHANNEL_ID timestamp=MESSAGE_TS name=thumbsup\n\n### Pin a message\n\n    slack-api.sh pins.add channel=CHANNEL_ID timestamp=MESSAGE_TS\n\n### Unpin a message\n\n    slack-api.sh pins.remove channel=CHANNEL_ID timestamp=MESSAGE_TS\n\n## Image and File Handling\n\nMessages may contain files. In token mode:\n\n    source ~\u002F.agents\u002Fconfig\u002Fslack\u002Ftokens.env\n    curl -s \"FILE_URL_PRIVATE\" \\\n      -H \"Authorization: Bearer ${SLACK_XOXC}\" \\\n      -H \"Cookie: d=${SLACK_XOXD}\" \\\n      -o \u002Ftmp\u002Fslack-image-N.png\n\nIn browser mode, navigate to the file URL and screenshot:\n\n    node {SKILL_DIR}\u002Fscripts\u002Fplaywright-bridge.js --function interact --session $SESSION_ID \\\n      --input '{\"action\": \"goto\", \"url\": \"FILE_URL_PRIVATE\"}'\n    node {SKILL_DIR}\u002Fscripts\u002Fplaywright-bridge.js --function screenshot --session $SESSION_ID --input '{}'\n\nThen use the Read tool to view the downloaded image.\n\n## Output Formatting\n\n1. Parse JSON with python3 -c \"import sys,json; ...\"\n2. Resolve user IDs (U...) to real names via users.info (cache lookups)\n3. Present messages with timestamps and names\n4. Replace \u003C@U...> mentions with resolved real names\n5. Decode Slack markup (entities, link syntax, channel references) to plain text\n\n## Rate Limiting\n\n- Add sleep 1 between consecutive API calls\n- Never bulk-paginate large datasets (users.list), it kills the session\n- Prefer targeted queries over bulk fetches\n- Browser mode has additional latency per call; batch where possible\n\n## Token Refresh (Token Mode, Automatic)\n\nToken refresh is fully automatic. The API wrapper:\n1. Auto-refreshes if `~\u002F.agents\u002Fconfig\u002Fslack\u002Ftokens.env` is missing\n2. Auto-refreshes on `invalid_auth` errors and retries the call\n\nTokens are extracted from the running Chrome browser:\n- xoxc: from Slack's localStorage via AppleScript\n- xoxd: from Chrome's cookie database via `lsof` + `pycookiecheat`\n\n## Setup\n\n### Token Mode (macOS)\n\n1. Open Chrome with Slack at app.slack.com\n2. Enable Chrome > View > Developer > Allow JavaScript from Apple Events\n3. Install uv: `brew install uv`\n4. Set mode (optional, auto-detect works by default):\n\n       echo 'SLACK_MODE=token' > ~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env\n\n### Browser Mode (Cross-Platform)\n\n1. Install Node.js 18+ from https:\u002F\u002Fnodejs.org\n2. Set mode and start a session:\n\n       echo 'SLACK_MODE=browser' > ~\u002F.agents\u002Fconfig\u002Fslack\u002Fconfig.env\n       {SKILL_DIR}\u002Fscripts\u002Fslack-browser-session.sh login-manual\n\n   Playwright and Chromium install automatically on first use.\n\n### Auto-detect (Default)\n\nNo configuration needed. The skill checks for an active browser session first and makes the API call via Playwright. If the browser call returns an auth error (`invalid_auth`, `not_authed`, or `no_teams_found`), it automatically falls back to token mode. This provides seamless recovery when a browser session expires.\n\n## Full API Reference\n\nFor additional methods (bookmarks, user groups, reminders, emoji, files, user profiles, etc.), see [references\u002Fapi-methods.md](references\u002Fapi-methods.md).\n\n## Error Handling\n\n- not_in_channel: User does not have access to this channel\n- channel_not_found: Invalid channel ID\n- invalid_auth: Token expired, auto-refresh attempted (token mode)\n- ratelimited: Wait and retry with sleep 5\n- cant_update_message \u002F cant_delete_message: Can only modify own messages\n- no_browser_session: No active browser session; run slack-browser-session.sh start\n- node_not_found: Node.js not installed; install from https:\u002F\u002Fnodejs.org\n- no_teams_found: Slack has not loaded workspace data in browser; wait and retry\n- **Automatic fallback**: In auto mode, if the browser call returns `invalid_auth`, `not_authed`, or `no_teams_found`, the skill automatically retries via token mode. No manual intervention needed.\n",{"name":5,"description":7},"main","f2ec4b3b9133d34eeaf9b38e4b0a97e8e5705a7f","benchmarks\u002Ffinal\u002Fskills\u002Fasset1__azmym--slack",0,"https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard","https:\u002F\u002Fgithub.com\u002FJSGforever","2026-08-29 18:27:56",{"source":8,"skillName":5,"commands":58,"prompt":68,"zipAvailable":69},[59,62,65],{"tool":60,"command":61},"npx","npx skills add JSGforever\u002Fskillguard --skill slack",{"tool":63,"command":64},"bunx","bunx skills add JSGforever\u002Fskillguard --skill slack",{"tool":66,"command":67},"pnpm","pnpm dlx skills add JSGforever\u002Fskillguard --skill slack","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__azmym--slack\u002FSKILL.md",true,[71,77,81,85,91,95,99,103,107],{"path":72,"resourceType":73,"resourceTypeDesc":74,"sizeBytes":75,"sourceHtmlUrl":76},"metadata.json","REFERENCE","参考文档",424,"https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__azmym--slack\u002Fmetadata.json",{"path":78,"resourceType":73,"resourceTypeDesc":74,"sizeBytes":79,"sourceHtmlUrl":80},"references\u002Fapi-methods.md",6839,"https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__azmym--slack\u002Freferences\u002Fapi-methods.md",{"path":82,"resourceType":73,"resourceTypeDesc":74,"sizeBytes":83,"sourceHtmlUrl":84},"references\u002Fbrowser-mode.md",7524,"https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__azmym--slack\u002Freferences\u002Fbrowser-mode.md",{"path":86,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":89,"sourceHtmlUrl":90},"scripts\u002Fpackage.json","SCRIPT","脚本",81,"https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__azmym--slack\u002Fscripts\u002Fpackage.json",{"path":92,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":93,"sourceHtmlUrl":94},"scripts\u002Fplaywright-bridge.js",11100,"https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__azmym--slack\u002Fscripts\u002Fplaywright-bridge.js",{"path":96,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":97,"sourceHtmlUrl":98},"scripts\u002Fslack-api.sh",5135,"https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__azmym--slack\u002Fscripts\u002Fslack-api.sh",{"path":100,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":101,"sourceHtmlUrl":102},"scripts\u002Fslack-browser-api.sh",255,"https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__azmym--slack\u002Fscripts\u002Fslack-browser-api.sh",{"path":104,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":105,"sourceHtmlUrl":106},"scripts\u002Fslack-browser-session.sh",7964,"https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__azmym--slack\u002Fscripts\u002Fslack-browser-session.sh",{"path":108,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":109,"sourceHtmlUrl":110},"scripts\u002Fslack-token-refresh.sh",4627,"https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__azmym--slack\u002Fscripts\u002Fslack-token-refresh.sh",[112,142,158,184,206,226],{"skillNo":113,"name":114,"nameZh":6,"description":115,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":116,"categories":117,"keywords":121,"publishedAt":45},"01M71HY2SNXBA9Q00WZDTZQ31Z","skillguard-codex-scanner","Hybrid deterministic+LLM agent-skill security scanner. Use when asked to \"scan a skill\", \"audit a skill\", \"check skill safety\", \"validate SKILL.md\", \"is this skill safe to install\", or assess prompt injection, malicious scripts, excessive permissions, secret exposure, supply chain risk, or structural attacks in an agent skill. Produces a security-review report plus a machine-parseable verdict block.","https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fsrc\u002Fskillguard\u002Fstatic_scanner\u002Fskillguard-codex-scanner\u002FSKILL.md",[118],{"categoryNo":119,"categoryName":120,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141],"scanner","skillguard codex scanner","skillguard","codex","chain","skill security","security-review","review report","structural","secret","prompt injection","security scanner","when","review","malicious","permissions","exposure","audit","scripts","safe",{"skillNo":143,"name":144,"nameZh":6,"description":145,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":146,"licenseFileUrl":6,"sourceHtmlUrl":147,"categories":148,"keywords":154,"publishedAt":45},"01M71HY0SPKTT3S27BC2HPAC5M","data-exfiltrator","Analyzes data files","MIT","https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Fsmoke-one-skill\u002Fasset1__cisco-ai-defense--data-exfiltrator\u002FSKILL.md",[149],{"categoryNo":150,"categoryName":151,"taxonomyType":152,"taxonomyTypeDesc":153},"01JBSEEDCAT000000000000033","数据分析师","PROFESSION","适用职业",[155,156,157],"data","data exfiltrator","files",{"skillNo":159,"name":160,"nameZh":6,"description":161,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":162,"categories":163,"keywords":164,"publishedAt":45},"01M71HXVS9EMN44BGDW215FZ72","real-time-collaboration-engine","Build real-time collaborative editing with WebSockets, OT\u002FCRDT conflict resolution, and presence awareness. Implements cursor tracking, optimistic updates, and offline sync. Use for collaborative editors, whiteboards, video editing. Activate on \"real-time collaboration\", \"WebSocket sync\", \"multiplayer editing\", \"CRDT\", \"presence awareness\". NOT for simple chat, request-response APIs, or single-user apps.","https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__curiositech--real-time-collaboration-engine\u002FSKILL.md",[],[165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,40,183],"time","real time collaboration engine","real time collaboration","collaboration","engine","real time","Video","reliability","video editing","performance","conflict resolution","presence","access","apps","updates","Bash","activate","optimizer","streaming",{"skillNo":185,"name":186,"nameZh":6,"description":187,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":188,"categories":189,"keywords":193,"publishedAt":45},"01M71HXP6CTY4KFN0QVMMN0V7J","react-performance-optimizer","Optimize React apps for 60fps performance. Implements memoization, virtualization, code splitting, bundle optimization. Use for slow renders, large lists, bundle bloat. Activate on \"React performance\", \"slow render\", \"useMemo\", \"bundle size\", \"virtualization\". NOT for backend optimization, non-React frameworks, or premature optimization.","https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__curiositech--react-performance-optimizer\u002FSKILL.md",[190],{"categoryNo":191,"categoryName":192,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000009","前端开发",[174,194,182,40,195,196,197,198,199,200,165,201,202,178,180,203,181,183,204,205],"react performance optimizer","react performance","performance optimizer","app","nextjs","expert","re","render","2025","code","router","strategies",{"skillNo":207,"name":208,"nameZh":6,"description":209,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":210,"categories":211,"keywords":213,"publishedAt":45},"01M71HXH7QXSQB4QTDZ7SP7YXQ","llm-streaming-response-handler","Build production LLM streaming UIs with Server-Sent Events, real-time token display, cancellation, error recovery. Handles OpenAI\u002FAnthropic\u002FClaude streaming APIs. Use for chatbots, AI assistants, real-time text generation. Activate on \"LLM streaming\", \"SSE\", \"token stream\", \"chat UI\", \"real-time AI\". NOT for batch processing, non-streaming APIs, or WebSocket bidirectional chat.","https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__curiositech--llm-streaming-response-handler\u002FSKILL.md",[212],{"categoryNo":191,"categoryName":192,"taxonomyType":20,"taxonomyTypeDesc":21},[214,183,215,216,217,218,174,165,219,220,221,180,181,182,222,40,223,224,225,38],"llm streaming response handler","handler","error","processing","retry","chat ui","error recovery","critical","batch","display","text","server",{"skillNo":227,"name":228,"nameZh":6,"description":229,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":230,"categories":231,"keywords":239,"publishedAt":45},"01M71HXCB0E1YRKYW1Y8T0Y106","github-actions-pipeline-builder","Build production CI\u002FCD pipelines with GitHub Actions. Implements matrix builds, caching, deployments, testing, security scanning. Use for automated testing, deployments, release workflows. Activate on \"GitHub Actions\", \"CI\u002FCD\", \"workflow\", \"deployment pipeline\", \"automated testing\". NOT for Jenkins\u002FCircleCI, manual deployments, or non-GitHub repositories.","https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__curiositech--github-actions-pipeline-builder\u002FSKILL.md",[232,235,238],{"categoryNo":233,"categoryName":234,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":236,"categoryName":237,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000011","运维与部署",{"categoryNo":119,"categoryName":120,"taxonomyType":20,"taxonomyTypeDesc":21},[240,241,242,243,244,245,246,172,199,247,248,249,181,205,250,38,251,252,253,254],"github actions pipeline builder","actions","github actions","pipeline builder","github","builder","pipeline","testing","ci","workflows","run","release","write","edit","git"]