Agent Browser CLI
vercel-labs/agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking…
“Send, read, and manage Slack messages”
$ npx skills add vellum-ai/vellum-assistant --skill slack -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install vellum-ai/vellum-assistant slack --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/vellum-ai/vellum-assistant.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/slack .claude/skills/slack && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "slack" agent skill from https://github.com/vellum-ai/vellum-assistant/tree/main/skills/slack into .claude/skills/slack/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "slack", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/vellum-ai/vellum-assistant/tree/main/skills/slackType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add vellum-ai/vellum-assistant --skill slack -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install vellum-ai/vellum-assistant slack --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/vellum-ai/vellum-assistant.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/slack .agents/skills/slack && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "slack" agent skill from https://github.com/vellum-ai/vellum-assistant/tree/main/skills/slack into .agents/skills/slack/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "slack", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add vellum-ai/vellum-assistant --skill slack -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install vellum-ai/vellum-assistant slack --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/vellum-ai/vellum-assistant.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/slack .cursor/skills/slack && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "slack" agent skill from https://github.com/vellum-ai/vellum-assistant/tree/main/skills/slack into .cursor/skills/slack/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "slack", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/vellum-ai/vellum-assistant.git --path skills/slack--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add vellum-ai/vellum-assistant --skill slack -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install vellum-ai/vellum-assistant slack --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/vellum-ai/vellum-assistant.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/slack .gemini/skills/slack && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "slack" agent skill from https://github.com/vellum-ai/vellum-assistant/tree/main/skills/slack into .gemini/skills/slack/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "slack", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install vellum-ai/vellum-assistant slackInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add vellum-ai/vellum-assistant --skill slack -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/vellum-ai/vellum-assistant.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/slack .github/skills/slack && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "slack" agent skill from https://github.com/vellum-ai/vellum-assistant/tree/main/skills/slack into .github/skills/slack/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "slack", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add vellum-ai/vellum-assistant --skill slack -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install vellum-ai/vellum-assistant slack --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/vellum-ai/vellum-assistant.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/slack .opencode/skills/slack && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "slack" agent skill from https://github.com/vellum-ai/vellum-assistant/tree/main/skills/slack into .opencode/skills/slack/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "slack", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
slackSlack is a skill in vellum-ai/vellum-assistant (1.4k stars). Its SKILL.md is about 4.6k tokens, with 5 other files in the folder (scripts, assets). Licence: MIT.
3 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 844117a. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships 4 files in scripts/ (TypeScript), which the agent can run.
Shell commands in SKILL.md call:
bunFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
files.slack.comAlso links to:
api.slack.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Designed for Vellum personal assistants
From compatibility in the SKILL.md frontmatter.
Slack loads about 4.6k tokens when it runs. Until then it costs about 11 tokens; SKILL.md has 2,404 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from vellum-ai/vellum-assistant at commit 844117a, republished under its MIT licence (© vellum-ai). 2,404 words, ~4,643 tokens.
.claude/skills/slack/SKILL.md (or your agent's skills folder). This skill also uses 5 other files; get the full folder from GitHub.You help users interact with their Slack workspace.
Sending text is its own command: assistant channels send. It posts through the same path a reply takes, so the message is threaded where you name a thread, rendered the way your other messages are, and recorded in the chat's conversation once Slack acknowledges it. That record is what lets you see later what you said, and what lets a reaction or an edit on that post find it again.
Everything else is the Slack Web API, through one of two doors. As the assistant's own bot: assistant channels request slack <path>, which resolves the bot credential from the channel so you never name a provider (assistant oauth request --provider slack_channel is the same bot door under its provider name). As the person who connected the slack integration: assistant oauth request --provider slack <path>, for search.messages and anything that needs the installer's reach. Reading, reactions, opening a DM, uploading a file, and any method with no first-class command go through them. Use relative Slack API method paths such as /conversations.history; the provider supplies the Slack host.
A message posted with /chat.postMessage reaches Slack but is not recorded in the chat's conversation, so recall will not find it (reading Slack back will) and nothing can resolve a reaction to it. Use the send command for text, and reach for chat.postMessage only for a shape the send command does not carry, such as Block Kit.
In a Slack turn, the reply is the door. When you are already answering in a chat, just reply; that reply is delivered and recorded for you. The send command is for posting somewhere you are not, or at a time nobody asked.
Two Slack credentials can exist. They act as different identities and reach different things, so the right one depends on the operation, not only on which is configured.
| Provider | Sends | Acts as | Reaches |
|---|---|---|---|
slack_channel | the bot token | the assistant | channels the bot has joined |
slack | the installer's user token | that person | channels that person is in, and search.messages |
Posting: slack_channel. The send command always posts as the bot, which is the assistant's own identity, and takes no provider. The distinction still matters for a Web API post: a message sent through slack arrives from the person who connected it, not from the assistant. Where that is the only credential present, say so before posting rather than posting as them silently.
search.messages: slack only. It is a user-token method. --provider slack_channel sends the bot token even on an install that stored a user token, so it cannot serve search at all.
Everything else: whichever is present, preferring slack_channel when both are. Reach differs rather than one being better: the bot sees channels it was invited to, the user token sees channels that person belongs to.
A workspace has only slack when Slack was connected as an integration without running the setup wizard, which means no bot. oauth status <provider> reports whether a given one holds a connection. Passing a provider that holds none fails with a not-configured error rather than falling back on its own.
Use these scripts to resolve Slack channel and user names to IDs. Results are cached locally so repeated lookups are free (no API calls).
| Command | Description |
|---|---|
bun skills/slack/scripts/slack-resolve.ts channel <name> | Resolve a channel name to its ID |
bun skills/slack/scripts/slack-resolve.ts user <name-or-email> | Resolve a user display name or email to their ID |
bun skills/slack/scripts/slack-resolve.ts channels [--refresh] | List all cached channels, or refresh the cache |
All scripts return JSON:
{ "ok": true, "data": { "id": "C...", "name": "general", ... } }{ "ok": false, "error": "..." }The cache is stored locally under $VELLUM_WORKSPACE_DIR/data/slack-skill/. On first use the script fetches all channels/users from Slack and caches them. Subsequent lookups read from the cache with no API calls. Pass --refresh to force a refresh.
The send command names the channel, the chat, and the text. It takes no provider and no token.
assistant channels send slack C0123456789 --text "Hello from the assistant!"Add --thread <ts> to post inside a thread, --plain to send the text verbatim instead of the channel's rich rendering, and --json for a machine-readable result naming every message id Slack acknowledged, plus the conversation the post was recorded in when a record was written.
The command refuses a channel it cannot address before anything is sent, and reports a failure rather than a success when Slack does not acknowledge the post. If it reports that the outcome is unknown, the message may still have gone out: check the chat before sending again.
Two commands reach the Slack Web API, and both send the token from inside the assistant. assistant channels request slack <path> acts as the bot, resolving the bot credential from the channel id. assistant oauth request --provider <key> <path> names the credential by provider: slack_channel is that same bot token, stored by the setup wizard with no OAuth flow involved; slack is the separate OAuth integration that acts as the person who connected it. Pass relative method paths; do not include a host.
These two commands are the only way to call the Slack Web API. Never fetch a Slack token yourself (assistant credentials reveal, an environment variable, a pasted value) and never call slack.com/api with curl or any other HTTP client: a token that reaches a shell command line is written into the transcript and the tool log, where no redaction applies. The doors send the token from inside the assistant and never show it to you.
The examples below use assistant oauth request --provider slack_channel, the bot door under its provider name, since reading a channel the bot has joined is what it is for; assistant channels request slack makes the same call. See Which provider to pass before reaching for one on a workspace that has no bot, or for search.messages.
General pattern:
assistant oauth request --provider slack_channel \
-X POST \
-d '{"channel":"C0123456789","limit":20}' \
/conversations.history --jsonThe model knows the full Slack API from training data. Refer to https://api.slack.com/methods for the complete list of available endpoints.
assistant oauth request --provider slack_channel \
-X POST \
-d '{"channel":"C0123456789","limit":20}' \
/conversations.history --jsonassistant oauth request --provider slack_channel \
-X POST \
-d '{"channel":"C0123456789","ts":"1716000000.000001"}' \
/conversations.replies --jsonWhen someone asks what you sent them earlier ("what did you send me this morning", "quote the digest from yesterday"), look in this order: the current conversation first; then recall, which searches your other conversations; then Slack itself, for anything older.
Anything you posted with the send command is recorded in the chat's conversation, so recall finds it. A post made with chat.postMessage is not, which is why reading Slack back is sometimes the only way to find one.
Reading Slack back is three calls on slack_channel. That is your own bot identity, and it is the right one here: a DM with you is your app's own DM, the posts you are looking for were made as the bot, and the history scopes this needs (im:history, mpim:history, channels:history, groups:history) are ones the app setup already requests.
Know where you are. When your <turn_context> carries chat_id (and thread_id for a message in a thread), that is the chat. Otherwise the person's contact record has the DM as externalChatId (see User Resolution below).
Read the top level. conversations.history returns only top-level messages, never thread replies. In a DM with you, every proactive post you made (a digest, a notification, a check-in from a run of your own) is top-level and appears here directly. Each thread you have taken part in appears only as its parent, carrying reply_count, latest_reply, and reply_users.
Do not put the time window you were asked about into oldest here: history filters by each parent's own timestamp, and a thread started days ago can hold a reply you made this morning. Read recent parents by count instead, and follow response_metadata.next_cursor while the parents are still newer than the window you care about.
assistant oauth request --provider slack_channel \
-X POST \
-d '{"channel":"D0123456789","limit":100}' \
/conversations.history --jsonRead the threads you replied in. Your own user id comes from auth.test (user_id in the response). Keep the parents whose reply_users includes it and whose latest_reply is not older than the window; fetch each of those threads. The first message returned is the parent, the rest are the replies in order; pick the replies whose ts falls in the window, and follow next_cursor on a long thread.
assistant oauth request --provider slack_channel /auth.test --json
assistant oauth request --provider slack_channel \
-X POST \
-d '{"channel":"D0123456789","ts":"1756800000.000100","limit":200}' \
/conversations.replies --jsonIn an agent-style DM, every conversation the person starts with you is its own thread, so what you said in an earlier chat lives in that chat's replies, not in the thread you are answering from now. The parents from step 2 are the list of those chats; step 3 reads the ones you spoke in.
Do not reach for search.messages here. It is a user-token method: on slack_channel it fails with not_allowed_token_type, and on slack it would read as the person who connected the integration, with their reach, which is not what re-reading your own DM calls for.
If any of these calls fails with missing_scope, the installed app holds fewer scopes than the setup requests. Do not work around it: assistant channels get slack re-probes the install and names the missing scopes with the reinstall step, and the slack-app-setup skill walks the reconnect.
assistant oauth request --provider slack_channel \
-X POST \
-d '{"channel":"C0123456789","timestamp":"1716000000.000001","name":"thumbsup"}' \
/reactions.add --jsonThe send command renders ordinary markdown the way a reply is rendered, and that covers more than it sounds like: headings, lists, task lists, blockquotes, code with a language, tables with their alignment, images, and dividers all become their native Slack blocks. Write GFM and it arrives formatted. Reach for Block Kit only for something markdown has no way to say, such as buttons or a custom section layout, and know that a post made this way is not recorded.
assistant oauth request --provider slack_channel \
-X POST \
-d '{
"channel":"C0123456789",
"text":"Fallback text",
"blocks":[
{"type":"header","text":{"type":"plain_text","text":"Weekly Update"}},
{"type":"section","text":{"type":"mrkdwn","text":"*Project Alpha*: on track\n*Project Beta*: needs review"}}
]
}' \
/chat.postMessage --jsonFile uploads use a multi-step flow: get an upload URL, upload the file, then complete the upload. The send command carries text only, so a file still goes this way.
# Step 1: Get an upload URL
assistant oauth request --provider slack_channel \
-X POST \
-d '{"filename":"notes.txt","length":42}' \
/files.getUploadURLExternal --json
# Step 2: Upload file content to the returned upload_url (use curl directly)
# Step 3: Complete the upload
assistant oauth request --provider slack_channel \
-X POST \
-d '{"files":[{"id":"FILE_ID","title":"Meeting Notes"}],"channel_id":"C0123456789"}' \
/files.completeUploadExternal --jsonA file shared in a message arrives on the message's files entries. Each carries url_private_download (or url_private) on files.slack.com, which takes the same token as the Web API, so the same command reads it. Pass the absolute URL as given and write the bytes with -o; the response is the file itself, not a JSON envelope.
assistant oauth request --provider slack_channel \
-o /tmp/shot.png \
"https://files.slack.com/files-pri/T0123456789-F0123456789/download/shot.png"The token needs files:read; one without it is answered with a sign-in page instead of the file. The bot has it from the app manifest. The slack integration requests it when it connects; a connection made before that keeps working for everything else, and every request through it comes back with a hint naming the missing scope until the person reconnects from Integrations. Pass that on rather than retrying. Do not fetch the URL with curl or paste a token into a shell: the command is the only place the token is allowed to be.
Takes slack, not slack_channel: search.messages is a user-token method, and the bot token cannot call it. A workspace with no slack connection cannot search this way; say so instead of reporting an empty result.
assistant oauth request --provider slack \
"/search.messages?query=project+launch+in%3A%23general" --jsonassistant oauth request --provider slack_channel \
-X POST \
-d '{"users":"U0123456789"}' \
/conversations.open --jsonbun skills/slack/scripts/slack-resolve.ts channel general to get the channel ID.assistant oauth request --provider slack_channel.bun skills/slack/scripts/slack-resolve.ts user <name> to get the user ID, then conversations.open to get the DM channel ID, then post to that DM channel ID with the send command.When you need to send a DM or look up a Slack user by name, check contacts first to avoid redundant API calls:
Before calling the resolve script: Use contact_search with query: "<name>" and channel_type: "slack". If a matching contact has externalUserId (Slack user ID) and externalChatId (DM channel ID), skip the API lookups and post to the DM channel ID with the send command.
When contact_search returns notes for the recipient, use them to inform the message's tone, formality, and content. Contact notes capture relationship context and communication preferences that should shape how you write to this person.
After resolving via script: When you had to use slack-resolve.ts user or conversations.open to resolve a user, save the contact with contact_upsert so you can find them by name next time. External Slack IDs (user ID, DM channel ID) are cached automatically by the messaging layer and should not be passed through contact_upsert.
Channel privacy must be respected at all times:
is_private on each channel before sharing content elsewhereWhen you post into a chat where a conversation is already running, thread it. Name the thread's parent timestamp with --thread:
assistant channels send slack C0123456789 \
--thread 1716000000.000001 \
--text "Replying in thread"When you are answering a Slack turn you are already in, reply instead: that reply is threaded and recorded without a command.
Before making any Slack API calls, verify that Slack is connected. If not connected, load the slack-app-setup skill (skill_load with skill: "slack-app-setup") and follow its guided flow. Do NOT improvise setup instructions -- the slack-app-setup skill is the single source of truth. Slack uses Socket Mode and does not require redirect URLs or any OAuth flow.
If a Slack API call fails due to missing or invalid credentials -- for example, an error indicating that the token is missing or invalid -- do NOT attempt to fix the credentials manually. Instead, load the slack-app-setup skill (skill_load with skill: "slack-app-setup") and follow its guided flow to set up or reconnect Slack. Tell the user something like "Slack needs to be reconnected" and start the setup skill.
chat.postMessage with blocks via assistant oauth request --provider slack_channel, knowing the post is not recorded. Headings, tables, lists, and code blocks do not need this; write them as markdown.assistant notifications send via bash is fine -- it lets the notification router pick the best channel© vellum-ai, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 5 other files (scripts, assets) in skills/slack of vellum-ai/vellum-assistant.
Open the folder on GitHubat commit 844117a
Slack next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Slack this skillvellum-ai/vellum-assistant | 1.4k | — | ~4.6k | Automated safety check: Pass | MIT | |
| Agent Browser CLIvercel-labs/agent-browser | 44k | 24 repos | ~864 | Automated safety check: Pass | Apache-2.0 | |
| Slack GIF Creatoranthropics/skills | 180k | 29 repos | ~2k | Automated safety check: Pass | Apache-2.0 | |
| Code Design Rationale Investigatorcursor/plugins | 10k | 9 repos | ~2.6k | Automated safety check: Pass | None | |
| Electron App Automationvercel-labs/agent-browser | 44k | 5 repos | ~1.7k | Automated safety check: Pass | Apache-2.0 | |
| Slack Browser Automationvercel-labs/agent-browser | 44k | 1 repos | ~2.1k | Automated safety check: Pass | Apache-2.0 |
vercel-labs/agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking…
anthropics/skills
Provides Slack size and frame limits, Python animation helpers and validators for building animated GIFs sized for emoji and messages.
cursor/plugins
Digs into why code is shaped the way it is by checking git history, pull requests and connected tools in parallel, then reporting a cited read on the tradeoffs.
vercel-labs/agent-browser
Automates Electron desktop apps such as VS Code, Slack or Discord by connecting agent-browser to their Chrome DevTools Protocol port.
vercel-labs/agent-browser
Drives the Slack web app with the agent-browser CLI to check unread channels, search, read channel details and extract information, with screenshots as evidence.
ComposioHQ/composio
Route and complete Composio work across Composio For You and Composio Platform.
vellum-ai/vellum-assistant
Create and configure a GitHub App so the assistant can push commits, open PRs, and comment under its own bot identity.
vellum-ai/vellum-assistant
Connect a Discord bot to the assistant via the Discord Gateway with guided application creation and intent configuration
vellum-ai/vellum-assistant
Create and configure a Sentry internal integration so the assistant can manage issues, alerts, and releases under its own identity
vellum-ai/vellum-assistant
Ingest a large dataset into memory as a skimmed map. An agent skill from vellum-ai/vellum-assistant.
vellum-ai/vellum-assistant
A skill your agent uses when the user wants to build, scaffold, ship, or edit a Vellum plugin that bundles multiple surfaces (hooks, tools, skills, and more) into one installable package.
vellum-ai/vellum-assistant
Connect a Slack app to the Vellum Assistant via Socket Mode.
Works with
Run `npx skills add vellum-ai/vellum-assistant --skill slack -a claude-code`. Or copy the skill folder (skills/slack in vellum-ai/vellum-assistant) into .claude/skills/slack in your project. Claude Code loads it when a task matches its description.
Run `npx skills add vellum-ai/vellum-assistant --skill slack -a codex`. Or copy the skill folder (skills/slack in vellum-ai/vellum-assistant) into .agents/skills/slack in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add vellum-ai/vellum-assistant --skill slack -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/slack, .gemini/skills/slack, .github/skills/slack and .opencode/skills/slack in your project.
Going by SKILL.md and its folder, Slack needs TypeScript for the scripts in its folder and the command-line tools its instructions call (bun). Compatibility (from SKILL.md): Designed for Vellum personal assistants.
SKILL.md names 2 domains. In commands or code: files.slack.com; the agent is likely to contact it when it follows the instructions. As links in the text: api.slack.com. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Slack is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.6k tokens (SKILL.md is roughly 19k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Slack: Agent Browser CLI (vercel-labs/agent-browser, 44k stars), Slack GIF Creator (anthropics/skills, 180k stars), Code Design Rationale Investigator (cursor/plugins, 10k stars) and Electron App Automation (vercel-labs/agent-browser, 44k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
vellum-ai (a GitHub organization) maintains it in vellum-ai/vellum-assistant, which has 1,400 GitHub stars. The repository holds 108 skills in this directory. The repository was last updated on October 9, 2026.
Source: vellum-ai/vellum-assistant on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.