{
  "markdown": "# agent-slack\n\nSlack automation CLI for AI agents (TypeScript + Bun).\n\nGuiding principle:\n\n- **Token-efficient** — (compact JSON, minimal duplication, and empty/null fields pruned) so LLMs can consume results cheaply.\n- **Zero-config auth** — Auth just works if you have Slack Desktop (with fallbacks available). No Python dependency.\n- **Human-in-the-loop** — When appropriate (not in CI environments), loop humans in. Ex: `message compose`\n  <img width=\"1228\" height=\"741\" alt=\"image\" src=\"https://github.com/user-attachments/assets/92ecbb71-18ca-4516-a874-c83c154b0709\" />\n\n## Getting started\n\nInstall via Bun (recommended):\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/stablyai/agent-slack/main/install.sh | sh\n```\n\nOR npm global install (requires Node >= 22.5):\n\n```bash\nnpm i -g agent-slack\n```\n\nOR run via Nix flake:\n\n```bash\nnix run github:stablyai/agent-slack\n```\n\n## At a glance\n\n- **Read**: fetch a message, browse channel history, list full threads\n- **Search**: messages + files (with filters)\n- **Artifacts**: auto-download snippets/images/files to local paths for agents\n- **Write**: send now or schedule delivery, edit/delete messages, add reactions (bullet lists auto-render as native Slack rich text)\n- **Compose & drafts**: open a browser editor (`message compose`), or manage Slack-native drafts that show up in your Slack client (`message draft`)\n- **Channels**: list conversations, create channels, and invite users by id/handle/email\n- **Canvas**: create, edit, and fetch Slack canvases as Markdown\n\n## Agent skill\n\nThis repo ships an agent skill at `skills/agent-slack/` compatible with Claude Code, Codex, Cursor, etc\n\nTreat the installed CLI's `agent-slack --help` and `agent-slack <command> --help` output as authoritative for supported commands and flags.\n\n**Install via [skills.sh](https://skills.sh)** (recommended):\n\n```bash\nnpx skills add stablyai/agent-slack\n```\n\n<details>\n<summary>Manual installation</summary>\n    \n```bash\nbash ./scripts/install-skill.sh\n```\n\n</details>\n\n## Command map (high level)\n\n```text\nagent-slack\n├── update                         # self-update (detects npm/bun/binary)\n├── auth\n│   ├── whoami\n│   ├── test\n│   ├── import-desktop\n│   ├── import-brave\n│   ├── import-chrome\n│   ├── import-firefox\n│   └── parse-curl\n├── message\n│   ├── get   <target>             # fetch 1 message (+ thread meta )\n│   ├── list  <target>             # fetch thread or recent channel messages\n│   ├── send  <target> [text]      # send / reply / schedule (supports --attach, --blocks)\n│   ├── scheduled\n│   │   ├── list                   # list pending scheduled messages\n│   │   └── cancel <id>            # cancel a pending scheduled message\n│   ├── compose <target> [text]    # open Slack-like editor in browser\n│   ├── draft                      # Slack-native drafts (appear in your Slack client)\n│   │   ├── list                   # list Slack-native drafts\n│   │   ├── create <target> <text> # create a Slack-native draft (supports --attach)\n│   │   ├── update <id> <text>     # replace a draft's text (supports --attach)\n│   │   └── delete <id>            # delete a draft\n│   ├── edit  <target> <text>      # edit a message\n│   ├── delete <target>            # delete a message\n│   └── react\n│       ├── add    <target> <emoji>\n│       └── remove <target> <emoji>\n├── channel\n│   ├── list                        # list conversations (user-scoped or all)\n│   ├── new                         # create channel\n│   └── invite                      # invite users to channel\n├── user\n│   ├── list\n│   └── get <user>\n├── search\n│   ├── all      <query>           # messages + files\n│   ├── messages <query>\n│   └── files    <query>\n├── workflow\n│   ├── list    <channel>          # workflows bookmarked in a channel\n│   ├── preview <trigger-id>       # trigger metadata (no side effects)\n│   ├── get     <id>               # workflow definition + form fields\n│   └── run     <trigger-id>       # trip a workflow trigger\n└── canvas\n    ├── create                     # markdown file/blob → canvas\n    ├── edit <canvas-url-or-id>    # replace/insert/delete/rename a canvas\n    └── get <canvas-url-or-id>     # canvas → markdown\n```\n\nNotes:\n\n- Slack data commands output aggressively pruned JSON (`null`/empty fields removed); help, update, and some authentication setup commands output text.\n- Attached files are auto-downloaded and returned as absolute local paths.\n\n## Authentication (no fancy setup)\n\nOn macOS and Windows, authentication happens automatically:\n\n- Default: reads Slack Desktop local data (no need to quit Slack)\n- Fallbacks: if that fails, tries Chrome/Brave/Firefox extraction (macOS)\n\nYou can also run manual imports:\n\n```bash\nagent-slack auth whoami\nagent-slack auth import-desktop\nagent-slack auth import-brave\nagent-slack auth import-chrome\nagent-slack auth import-firefox\nagent-slack auth test\n```\n\n> [!NOTE]\n> `import-brave` / `import-chrome` read tokens from a logged-in Slack tab via AppleScript. Both browsers ship with **Allow JavaScript from Apple Events** disabled by default — enable it in **View → Developer** before running these commands. macOS will prompt for your password the first time.\n\nAlternatively, set env vars:\n\n```bash\nexport SLACK_TOKEN=\"xoxc-...\"      # browser token\nexport SLACK_COOKIE_D=\"xoxd-...\"   # cookie d\nagent-slack auth test\n```\n\nOr use a standard Slack token (xoxb/xoxp):\n\n```bash\nexport SLACK_TOKEN=\"xoxb-...\"\nagent-slack auth test\n```\n\n## Targets: URL or channel\n\n`message get` / `message list` accept either a Slack message URL or a channel reference:\n\n- URL: `https://workspace.slack.com/archives/<channel>/p<digits>[?thread_ts=...]`\n- Channel: `#general` (or bare `general`) or a channel ID like `C0123...`\n\nIn practice:\n\n```bash\n# Get a single message by channel + ts\nagent-slack message get \"#general\" --ts \"1770165109.628379\"\n\n# List a full thread by channel + thread root ts\nagent-slack message list \"#general\" --thread-ts \"1770165109.000001\"\n```\n\nIf you have multiple workspaces configured and you use a channel **name** (`#channel` / `channel`), you must pass `--workspace` (or set `SLACK_WORKSPACE_URL`).\n`--workspace` accepts a full URL or a unique substring selector:\n\n```bash\nagent-slack message get \"#general\" --workspace \"https://stablygroup.slack.com\" --ts \"1770165109.628379\"\nagent-slack message get \"#general\" --workspace \"stablygroup\" --ts \"1770165109.628379\"\n```\n\n## Examples\n\n> [!TIP]\n> You should probably just use the skill for your agent instead of reading below.\n\n### Read messages / threads\n\n```bash\n# Single message (+ thread summary if threaded)\nagent-slack message get \"https://workspace.slack.com/archives/C123/p1700000000000000\"\n\n# Full thread for a message\nagent-slack message list \"https://workspace.slack.com/archives/C123/p1700000000000000\"\n\n# Recent channel messages (browse channel history)\nagent-slack message list \"#general\" --limit 20\n\n# Recent channel messages that are marked with :eyes:\nagent-slack message list \"#general\" --with-reaction eyes --oldest \"1770165109.000000\" --limit 20\n\n# Recent channel messages that do not have :dart:\nagent-slack message list \"#general\" --without-reaction dart --oldest \"1770165109.000000\" --limit 20\n```\n\nOptional:\n\n```bash\n# Include reactions + which users reacted\nagent-slack message get \"https://workspace.slack.com/archives/C123/p1700000000000000\" --include-reactions\n```\n\n### Compose a message (browser editor)\n\nOpens a Slack-like WYSIWYG editor in your browser for composing messages with full formatting support (bold, italic, strikethrough, links, lists, quotes, code, code blocks).\n\n```bash\n# Open editor for a channel\nagent-slack message compose \"#general\"\n\n# Open editor with initial text\nagent-slack message compose \"#general\" \"Here's my update\"\n\n# Open the editor and suppress link/media previews when sent\nagent-slack message compose \"#general\" \"Release notes: https://example.com\" --no-unfurl\n\n# Reply in a thread\nagent-slack message compose \"https://workspace.slack.com/archives/C123/p1700000000000000\"\n```\n\nAfter sending, the editor shows a \"View in Slack\" link to the posted message.\n\n`message compose` is send-capable. In CI, it skips the browser editor and immediately sends supplied text; do not use it for a compose-only request in a noninteractive environment.\n\n### Slack-native drafts\n\nManage drafts through Slack's own drafts API, so they show up natively in the user's Slack client (mobile and desktop) ready to review and send. Requires browser-style auth (xoxc/xoxd).\n\n> [!NOTE]\n> These commands use Slack's **undocumented** internal `drafts.*` client endpoints (the same ones the Slack app uses), authenticated with your own browser session. They act only as you, on your own drafts — nothing is exposed that you can't already see, and `create` posts nothing. But because the endpoints are unsupported: their behavior may change without notice, and on **Enterprise Grid** this style of session-token API use can be flagged by Slack's security/anomaly detection. This is the same auth model the rest of agent-slack already uses (`later`, `unreads`, `search`); use it where that's acceptable.\n\n```bash\n# List unsent drafts\nagent-slack message draft list\n\n# Draft a message to a channel (shows up in Slack's Drafts section)\nagent-slack message draft create \"#general\" \"Here's my update\"\n\n# Draft a thread reply\nagent-slack message draft create \"https://workspace.slack.com/archives/C123/p1700000000000000\" \"Looking into it\"\n\n# Replace a draft's text, or delete it\nagent-slack message draft update \"DR_ID\" \"Here's my revised update\"\nagent-slack message draft delete \"DR_ID\"\n\n# Attach local files to a draft (repeatable). On update, new files are\n# added to the draft's existing attachments rather than replacing them.\nagent-slack message draft create \"#general\" \"Latest numbers\" --attach ./q3.png --attach ./q3.csv\nagent-slack message draft update \"DR_ID\" \"Latest numbers\" --attach ./appendix.pdf\n```\n\n### Safe mode (enforced human-in-the-loop)\n\nSkill instructions like \"always use `draft`, never `send`\" are guidance an agent can ignore. Safe mode enforces it at the tool level — useful when an AI agent has access to `agent-slack` and you want a guarantee that nothing posts without human review.\n\n```bash\n# Env var (recommended for agent environments)\nexport AGENT_SLACK_SAFE_MODE=1\n\n# Or a global CLI flag\nagent-slack --safe-mode message send \"#general\" \"hello\"\n```\n\nWhile safe mode is active:\n\n- `message send` → redirected to the draft editor with the text pre-filled; you review and send from the browser. The output includes `\"safe_mode\": true` and `\"redirected_from\": \"send\"`, and a warning is printed to stderr. Flags the editor cannot represent (`--attach`, `--blocks`, `--schedule`, `--schedule-in`, `--reply-broadcast`) are rejected with an error instead of being silently dropped.\n- `message edit` and `message delete` → blocked with an error.\n- All read operations (`get`, `list`, `search`, etc.) and reactions are unchanged.\n\nThe env var accepts `1`, `true`, `yes`, or `on` (case-insensitive); anything else leaves safe mode off.\n\n### Reply, edit, delete, and react\n\n```bash\nagent-slack message send \"https://workspace.slack.com/archives/C123/p1700000000000000\" \"I can take this.\"\nagent-slack message send \"#alerts-staging\" \"here's the report\" --attach ./report.md\nagent-slack message send \"#announcements\" \"Deploy starts at 6pm.\" --schedule \"<future-iso-with-timezone>\"\nagent-slack message send \"U05BRPTKL6A\" \"Heads up before standup\" --schedule-in \"monday 9am\"\nagent-slack message edit \"https://workspace.slack.com/archives/C123/p1700000000000000\" \"I can take this today.\"\nagent-slack message delete \"https://workspace.slack.com/archives/C123/p1700000000000000\"\nagent-slack message react add \"https://workspace.slack.com/archives/C123/p1700000000000000\" \"eyes\"\nagent-slack message react remove \"https://workspace.slack.com/archives/C123/p1700000000000000\" \"eyes\"\n```\n\nChannel mode requires `--ts`:\n\n```bash\nagent-slack message edit \"#general\" \"Updated text\" --workspace \"myteam\" --ts \"1770165109.628379\"\nagent-slack message delete \"#general\" --workspace \"myteam\" --ts \"1770165109.628379\"\n```\n\n`message edit` and ordinary `message send` calls convert bullet/numbered lists to Slack native rich text. `message send --blocks` uses the supplied blocks instead, while `message send --attach` sends its initial comment as plain text without automatic list conversion. Inside auto-converted lists, inline mentions, broadcasts, emoji shortcodes, `<#C...>` channel references, and Slack manual links such as `<https://example.com/pull/42|PR #42>` are preserved as Slack elements. CommonMark links such as `[PR #42](https://example.com/pull/42)` are not converted into labeled link elements.\n\nSend options for `message send`:\n\n- `--attach <path>` upload a local file (repeatable; `<text>` is optional when attaching files)\n- `--blocks <path>` send raw [Block Kit](https://docs.slack.dev/block-kit/) blocks from a JSON file (or `-` for stdin). Bypasses the automatic markdown-to-rich-text conversion, unlocking header/divider/section/table blocks and other structured layouts. Cannot be combined with `--attach`.\n- `--reply-broadcast` when replying in a thread, also post the reply to the parent channel (Slack's \"Also send to #channel\" checkbox). For channel targets, pair with `--thread-ts`; for URL targets, the thread context is derived from the message. Not supported for DM targets; cannot be combined with `--attach`.\n- `--no-unfurl` suppress Slack link and media previews. Also available on `message compose`; cannot be combined with `--attach`.\n- `--schedule <time>` schedule delivery at an ISO 8601 timestamp with explicit timezone (for example `YYYY-MM-DDTHH:mm:ss-07:00`) or a Unix timestamp. The timestamp must be in the future and within Slack's 120-day scheduled-send limit. Works with `--blocks`, `--thread-ts`, `--reply-broadcast`, and `--no-unfurl`; cannot be combined with `--attach`.\n- `--schedule-in <duration>` schedule delivery after a duration or simple future phrase (`30m`, `3h`, `2d`, `tomorrow 9am`, `monday 9am`; phrases use your local timezone). Mutually exclusive with `--schedule`; cannot be combined with `--attach`.\n\nUpload files through `message send`:\n\n```bash\nagent-slack message send \"#general\" \"Coverage report\" --attach ./report.md\n```\n\nBroadcast a thread reply to the parent channel:\n\n```bash\nagent-slack message send \"#general\" \"Decision: shipping v2 today\" \\\n  --thread-ts \"1770160000.000001\" --reply-broadcast\n```\n\nScheduled sends use Slack's server-side scheduled message queue:\n\n```bash\n# Absolute time with explicit timezone; replace with a future value within 120 days\nagent-slack message send \"#general\" \"Reminder: deploy starts soon.\" \\\n  --schedule \"<future-iso-with-timezone>\"\n\n# Relative / natural future time\nagent-slack message send \"#general\" \"Monday launch checklist\" --schedule-in \"monday 9am\"\n\n# Scheduled thread reply with a Block Kit payload\nagent-slack message send \"#general\" \"fallback text\" \\\n  --thread-ts \"1770160000.000001\" --blocks /tmp/blocks.json --schedule-in \"3h\"\n```\n\nManage pending scheduled messages:\n\n```bash\nagent-slack message scheduled list\nagent-slack message scheduled list --channel \"#general\" --limit 25\nagent-slack message scheduled cancel \"Q1234ABCD\" --channel \"C12345678\"\n```\n\nExample — post a message with a native Slack table block:\n\n```bash\ncat > /tmp/blocks.json <<'EOF'\n[\n  {\n    \"type\": \"header\",\n    \"text\": { \"type\": \"plain_text\", \"text\": \"Weekly digest\" }\n  },\n  {\n    \"type\": \"table\",\n    \"rows\": [\n      [\n        { \"type\": \"raw_text\", \"text\": \"Name\" },\n        { \"type\": \"raw_text\", \"text\": \"Why\" }\n      ],\n      [\n        { \"type\": \"raw_text\", \"text\": \"Caveman MCP\" },\n        { \"type\": \"raw_text\", \"text\": \"~80% token cut on nav\" }\n      ]\n    ]\n  }\n]\nEOF\nagent-slack message send \"#alerts-staging\" --blocks /tmp/blocks.json\n```\n\nWhen `--blocks` is used, the positional `<text>` argument (if provided) is still sent as the message's `text` fallback (for notifications and unfurls).\n\n`message send` returns `channel_id` plus the posted `ts` and a `permalink` (for non-attachment sends). `thread_ts` appears only when replying in a thread. Scheduled sends return `scheduled_message_id` and `post_at` instead of `ts`/`permalink`.\n\n### List, create, and invite channels\n\n```bash\n# List conversations for current user (users.conversations)\nagent-slack channel list\n\n# List conversations for a specific user\nagent-slack channel list --user \"@alice\" --limit 50\n\n# List all workspace conversations (conversations.list)\nagent-slack channel list --all --limit 100\n\n# Create a public channel\nagent-slack channel new --name \"incident-war-room\"\n\n# Create a private channel\nagent-slack channel new --name \"incident-leads\" --private\n\n# Invite users by id, handle, or email\nagent-slack channel invite --channel \"incident-war-room\" --users \"U01234567,@alice,bob@example.com\"\n\n# Invite external Slack Connect users by email (restricted by default)\nagent-slack channel invite --channel \"incident-war-room\" --users \"partner@vendor.com\" --external\n\n# External invite with permission for invitees to invite others\nagent-slack channel invite --channel \"incident-war-room\" --users \"partner@vendor.com\" --external --allow-external-user-invites\n```\n\nNotes:\n\n- `channel list` returns a single page plus `next_cursor`; use `--cursor` to fetch the next page.\n- `channel list --all` and `channel list --user` are mutually exclusive.\n- `--external` maps to `conversations.inviteShared` and expects email targets.\n- External invites default to restricted mode (`external_limited=true`); add `--allow-external-user-invites` to disable that restriction.\n- External invites require Slack Connect permissions/scopes in your workspace.\n\n### Message get vs list\n\n**`message get`** fetches a single message. If the message is in a thread, it also returns thread metadata (reply count, participants) but **not** the full thread contents:\n\n```json\n{\n  \"message\": { \"ts\": \"...\", \"text\": \"...\", \"user\": \"U123\", ... },\n  \"thread\": { \"ts\": \"...\", \"length\": 6 }\n}\n```\n\n**`message list`** fetches the thread root plus all replies, or recent channel messages when no thread is specified. Use this when you need the full conversation:\n\n```json\n{\n  \"messages\": [\n    { \"ts\": \"...\", \"text\": \"...\", \"user\": \"U123\", ... },\n    { \"ts\": \"...\", \"text\": \"...\", \"user\": \"U456\", ... }\n  ]\n}\n```\n\nWhen to use which:\n\n- Use `get` to check a single message or see if there's a thread worth expanding\n- Use `list` to read an entire thread conversation\n- Use `list` on a channel (without `--thread-ts`) to browse recent channel messages\n- Use `list` with `--with-reaction` / `--without-reaction` plus `--oldest` to filter channel history by reaction markers\n\n### Files (snippets/images/attachments)\n\n`message get/list` auto-download attached files to an agent-friendly temp directory and return file metadata in `message.files[]`, including `name` when Slack provides the original filename and `path` for the local download. Failed downloads keep the attachment entry, preserve `message.files[].path` with a local `.download-error.txt` file, and include `message.files[].error`. `search messages` and `search all` use the same attachment shape for message results, while `search files` skips entries whose download fails. Use `search messages --content-type file` when you also need the source-message permalink for a reply.\n\n- macOS default: `~/.agent-slack/tmp/downloads/`\n\nAgents can read those paths directly (e.g. snippets as `.txt`, images as `.png`).\n\n### Search (messages + files)\n\n```bash\n# Search both messages and files\nagent-slack search all \"smoke tests failed\" --channel \"#alerts\" --after 2026-01-01 --before 2026-02-01\n\n# Search messages only\nagent-slack search messages \"stably ai\" --user \"@stablyai\" --channel general\n\n# Search files only (downloads files and returns local paths)\nagent-slack search files \"testing\" --content-type snippet --limit 10\n```\n\nTips:\n\n- For reliable results, include `--channel ...` (channel-scoped search scans history/files and filters locally).\n- Use `--workspace <url-or-unique-substring>` when using `#channel` names across multiple workspaces.\n\n<!-- AI search (assistant.search.*) is described in design.doc but not currently implemented. -->\n\n### Users\n\nTreat Slack user IDs beginning with `U` or `W` equivalently.\n\n```bash\n# List users (email requires appropriate Slack scopes; fields are pruned if missing)\nagent-slack user list --workspace \"https://workspace.slack.com\" --limit 200 | jq .\n\n# Get one user by id or handle\nagent-slack user get U12345678 --workspace \"https://workspace.slack.com\" | jq .\nagent-slack user get \"@alice\" --workspace \"https://workspace.slack.com\" | jq .\n\n# Open a DM or group DM with one to eight other users (the caller is implicit)\nagent-slack user dm-open \"@alice\" \"@bob\" --workspace \"https://workspace.slack.com\" | jq .\n```\n\n### Unreads (inbox view)\n\nSee all unread messages across channels, DMs, and threads in one place:\n\n```bash\n# Show all unreads with message content\nagent-slack unreads\n\n# Show only unread counts (no message content)\nagent-slack unreads --counts-only\n\n# Limit messages per channel (default 10)\nagent-slack unreads --max-messages 5\n\n# Include system messages (joins, leaves, topic changes)\nagent-slack unreads --include-system\n```\n\nOutput includes channels sorted by mention count, then unread count:\n\n```json\n{\n  \"channels\": [\n    {\n      \"channel_id\": \"C123...\",\n      \"channel_name\": \"general\",\n      \"channel_type\": \"channel\",\n      \"unread_count\": 5,\n      \"mention_count\": 2,\n      \"messages\": [...]\n    }\n  ],\n  \"threads\": {\n    \"has_unreads\": true,\n    \"mention_count\": 3\n  }\n}\n```\n\nNote: This feature uses the `client.counts` API which may be restricted in some Enterprise Grid workspaces (`team_is_restricted` error).\n\n### Later (saved messages)\n\nManage your saved-for-later messages (Slack's Later tab):\n\n```bash\n# List saved messages (in-progress by default)\nagent-slack later list\n\n# Show only counts per state\nagent-slack later list --counts-only\n\n# Filter by state: in_progress, completed, archived, all\nagent-slack later list --state completed\n\n# Save a message for later\nagent-slack later save \"https://workspace.slack.com/archives/C123/p1700000000000000\"\n\n# Mark as completed\nagent-slack later complete \"https://workspace.slack.com/archives/C123/p1700000000000000\"\n\n# Archive\nagent-slack later archive \"https://workspace.slack.com/archives/C123/p1700000000000000\"\n\n# Move back to in-progress\nagent-slack later reopen \"https://workspace.slack.com/archives/C123/p1700000000000000\"\n\n# Remove from saved\nagent-slack later remove \"https://workspace.slack.com/archives/C123/p1700000000000000\"\n\n# Set a reminder\nagent-slack later remind \"https://workspace.slack.com/archives/C123/p1700000000000000\" --in 1h\nagent-slack later remind \"https://workspace.slack.com/archives/C123/p1700000000000000\" --in tomorrow\n```\n\nNamed reminder days such as `tomorrow` and `monday` mean 9:00 in the CLI process's local timezone. Use a Unix timestamp when timezone precision matters.\n\n### Create, edit, or fetch a Canvas as Markdown\n\n```bash\n# Create from a local Markdown file\nagent-slack canvas create --file ./launch-plan.md --title \"Launch plan\"\n\n# Create from an inline Markdown blob\nagent-slack canvas create --markdown $'# Launch plan\\n\\n- [ ] Ship it' --title \"Launch plan\"\n\n# Add the new canvas as a channel tab (required on free Slack plans)\nagent-slack canvas create --file ./launch-plan.md --channel \"project-launch\"\n\n# Fetch an existing canvas as Markdown\nagent-slack canvas get \"https://workspace.slack.com/docs/T123/F456\"\nagent-slack canvas get \"F456\" --workspace \"https://workspace.slack.com\"\n\n# Replace the entire canvas (the default operation)\nagent-slack canvas edit \"F12345678\" --file ./revised-plan.md --workspace \"https://workspace.slack.com\"\n\n# Apply a section-level edit (look up section IDs with Slack's Canvas tools)\nagent-slack canvas edit \"F12345678\" --operation insert_after --section-id \"temp:C:SECTION\" \\\n  --markdown $'## Follow-up\\n\\n- [ ] Verify rollout' --workspace \"https://workspace.slack.com\"\n\n# Delete a section or rename the canvas\nagent-slack canvas edit \"F12345678\" --operation delete --section-id \"temp:C:SECTION\" \\\n  --workspace \"https://workspace.slack.com\"\nagent-slack canvas edit \"F12345678\" --operation rename --title \"Launch plan (final)\" \\\n  --workspace \"https://workspace.slack.com\"\n```\n\n`canvas create` requires exactly one of `--file <path>` or `--markdown <text>`. Use\n`--workspace <url-or-unique-substring>` to select a workspace when needed. The command returns\n`canvas: { id, title?, channel_id? }`. Imported browser credentials can create standalone\ncanvases; `--channel` requires a standard Slack token with Slack's `canvases:write` scope.\n\n`canvas edit` calls Slack's `canvases.edit` method and supports one operation per call:\n`insert_after`, `insert_before`, `insert_at_start`, `insert_at_end`, `replace`, `delete`, or\n`rename`. `replace` is the default and replaces the entire canvas unless `--section-id` is\nprovided. Content operations require exactly one Markdown source; `delete` requires a section ID;\n`rename` requires `--title`. Editing requires a standard token with Slack's `canvases:write` scope;\nimported browser credentials cannot edit canvases.\n\n## Developing / Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Check out our other OSS project\n\n[Orca](https://github.com/stablyai/orca) - ADE for 100x builders\n",
  "bytes": 25453,
  "sha": "1b0b015fd682ed74b3733041e92983fc6293929117e926f1b5b29712956d17e6",
  "repo_slug": "stablyai/agent-slack",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/skl_stablyai_agent_slack_agent_slack_79d88b25/readme"
}