From holla
Use holla CLI to interact with Slack — send messages, read threads, search, manage canvases, and more
npx claudepluginhub circlesac/holla-cli --plugin hollaThis skill uses the workspace's default tool permissions.
holla is a CLI tool that lets you interact with Slack as yourself (using your user token). All commands require `--workspace <name>` (or `-w`).
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Generates original PNG/PDF visual art via design philosophy manifestos for posters, graphics, and static designs on user request.
holla is a CLI tool that lets you interact with Slack as yourself (using your user token). All commands require --workspace <name> (or -w).
Authenticate first: holla slack auth login --workspace <name>
Check status: holla slack auth whoami --workspace <name>
# Send to a channel
holla slack chat send --channel "#general" --text "Hello" -w <ws>
# Reply to a thread
holla slack chat reply --channel "#general" --ts 1234567890.123456 --text "Reply" -w <ws>
# Multiline via stdin
cat <<'EOF' | holla slack chat send --channel "#general" -w <ws>
Line one
Line two
EOF
# Edit a message
holla slack chat edit --channel "#general" --ts 1234567890.123456 --text "Updated" -w <ws>
# Delete a message
holla slack chat delete --channel "#general" --ts 1234567890.123456 -w <ws>
--text accepts standard markdown (converted to Slack blocks automatically). Use --json to get { ts, channel, text } back after sending.
⚠️ holla expects STANDARD MARKDOWN, not Slack mrkdwn. holla converts to Slack blocks server-side. Do not pre-convert your text to Slack mrkdwn. A common mistake is "fixing"
**bold**to*bold*thinking Slack needs that — this DOUBLE-CONVERTS and the bold disappears.Rule of thumb: write the text exactly the way you'd write it in a normal Markdown document. Pass it as-is to
--text. Do not touch the asterisks.
| What you want | Write this | NOT this (common mistake) |
|---|---|---|
| Bold | **text** | *text* (renders as italic, or disappears) |
| Italic | *text* or _text_ | |
~text~ | ||
| Link | [text](url) | <url|text> (Slack-native — don't use) |
Tilde (~) as range separator: Slack interprets two ~ in the same text as strikethrough (e.g. 70~80% ... 20~30% strikes through everything between them). Use fullwidth tilde ~ (U+FF5E) instead — visually identical, no strikethrough trigger.
Bold adjacent to non-Latin text: **text** followed immediately by CJK characters (e.g. **회사**만) may render as _회사_만 with visible underscores. Add a space after the closing **: **회사** 만.
Slack requires <@USER_ID> format for mentions — plain names like @john won't notify anyone.
When the user asks you to send a message to a specific person (e.g. "send this to John"), you must mention that person using <@USER_ID> format so they receive a notification. Look up the user ID before drafting the message, and include the mention in the draft shown to the user — not just in the final sent message.
holla slack channels members --channel "#general" -w <ws> --json
U01234567)holla slack channels invite --channel "#general" --user @username -w <ws>
<@USER_ID> in the message text:
holla slack chat send --channel "#general" --text "Hey <@U01234567>, take a look" -w <ws>
--user argument rulesThe --user flag uses @ prefix to trigger name lookup. Without @, the value is treated as a raw user ID.
| Input | Behavior |
|---|---|
--user @name | Looks up by Slack username → resolves to ID |
--user U01234567 | Used as-is (raw ID) |
--user name | Treated as raw ID → will fail |
Always use @ prefix when passing a username.
# Channel history
holla slack channels history --channel "#general" -w <ws> --json
# Thread replies
holla slack channels history --channel "#general" --thread 1234567890.123456 -w <ws> --json
# Single message
holla slack chat get --channel "#general" --ts 1234567890.123456 -w <ws> --json
Use --all to auto-paginate. Use --limit <n> to control count.
holla slack search messages --query "keyword" -w <ws> --json
Options: --sort timestamp|score, --sort-dir asc|desc, --limit <n>, --page <n>
Since v26.3.10, search messages returns a permalink field in --json output — use it directly instead of constructing URLs manually. The permalink correctly points to the message within its thread.
# Read a canvas (outputs markdown)
holla slack canvases read --canvas <id> -w <ws>
holla slack canvases read --canvas <id> -w <ws> --json # includes id, title, markdown, timestamps
# Create (with optional auto-share)
holla slack canvases create --title "Title" --markdown "content" --channel "#general" -w <ws>
# Create from file via stdin (--stdio required)
cat document.md | holla slack canvases create --title "Title" --stdio -w <ws>
# Look up section IDs (required for targeted edits)
holla slack canvases sections --canvas <id> --contains "search text" -w <ws> --json
# Edit a specific section (replace, insert_before, insert_after, delete)
holla slack canvases edit --canvas <id> --operation replace --section-id <section-id> --markdown "new content" -w <ws>
# Edit via stdin (--stdio required)
cat content.md | holla slack canvases edit --canvas <id> --operation insert_at_end --stdio -w <ws>
# Append to end (no section-id needed)
holla slack canvases edit --canvas <id> --operation insert_at_end --markdown "more" -w <ws>
# Share
holla slack canvases access-set --canvas <id> --level read --channels "#general" -w <ws>
# Delete
holla slack canvases delete --canvas <id> -w <ws>
Operations: insert_at_start, insert_at_end, insert_before, insert_after, replace, delete
Important: Section IDs change after each edit. Always look up fresh IDs with sections before editing. The --contains filter requires at least one search term.
Canvas markdown limitations: The Slack Canvas API does not support bullet sub-items under numbered lists (e.g. 1. item → - sub). This causes canvas_creation_failed. The CLI auto-converts these to numbered sub-items (with a warning), but when writing markdown for canvases, prefer consistent nesting: bullets under bullets, or numbers under numbers.
holla slack channels list -w <ws> --json # List channels
holla slack channels info --channel "#general" -w <ws> # Channel info
holla slack channels members --channel "#general" -w <ws> --json # Members
holla slack channels topic --channel "#general" --topic "New topic" -w <ws>
holla slack reactions add --channel <ch> --ts <ts> --name thumbsup -w <ws>
holla slack pins add --channel <ch> --ts <ts> -w <ws>
holla slack stars add --channel <ch> --ts <ts> -w <ws>
holla slack bookmarks add --channel <ch> --title "Link" --link "https://..." -w <ws>
holla slack reminders add --text "Do thing" --time "in 1 hour" -w <ws>
holla slack files upload --channels "#general" --file ./doc.pdf -w <ws>
holla slack files download --file <file-id> -o ./output.pdf -w <ws>
holla slack users info --user @username -w <ws> --json
holla slack api <method> --body '{"key":"value"}' -w <ws> # Raw API passthrough
Note: holla slack api is a raw passthrough — messages sent via api chat.postMessage appear as bot, not as the user. Always use holla slack chat send / reply / edit for messaging.
All read commands support: --json (structured), --plain (tab-separated), or table (default).
Channels accept #name or ID. Users accept @name or ID. Fuzzy matching suggests corrections on typos.
After any write action (send, reply, edit, delete, reactions add/remove, mentions, etc.), always re-fetch the result to verify it worked correctly:
# After sending/editing a message — verify content and formatting
holla slack chat get --channel <ch> --ts <ts> -w <ws> --json
# After adding a reaction — verify it appears
holla slack channels history --channel <ch> --limit 1 -w <ws> --json
What to check:
<@USER_ID> resolve to the correct person? Is the mention actually visible?Never assume a write action succeeded — always verify.
After verification, always provide the permalink so the user can check the result themselves:
holla slack chat permalink --channel <ch> --ts <ts> -w <ws>
Report the permalink URL back to the user along with the verification result.