Skip to content

Add canvas creation from Markdown#116

Merged
nwparker merged 4 commits into
mainfrom
nwparker/create-canvas
Jul 18, 2026
Merged

Add canvas creation from Markdown#116
nwparker merged 4 commits into
mainfrom
nwparker/create-canvas

Conversation

@nwparker

@nwparker nwparker commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds agent-slack canvas create, giving agents a first-class way to create Slack canvases from either a local Markdown file or an inline Markdown blob.

  • accepts exactly one of --file <path> or --markdown <text>
  • supports an optional --title
  • supports --channel <id-or-name> to add the canvas as a channel tab (and cover Slack free plans, where channel_id is required)
  • uses the existing workspace selection, channel resolution, and auth auto-refresh paths
  • returns compact JSON as canvas: { id, title?, channel_id? }
  • rejects empty content and malformed success responses before presenting a false success

Authentication paths

Live testing found that Slack's public canvases.create API rejects imported xoxc browser credentials with not_allowed_token_type. Canvas creation now selects the appropriate API automatically:

  • standard Slack tokens use the official canvases.create API with Markdown document_content
  • imported browser credentials use Slack's multipart files.createCanvas Markdown path
  • --channel remains standard-token-only because the browser-auth path creates standalone canvases and cannot add a channel tab

Standard tokens require Slack's canvases:write scope.

Usage

# Create from a file
agent-slack canvas create --file ./launch-plan.md --title "Launch plan"

# Create from an inline Markdown blob
agent-slack canvas create --markdown $'# Launch plan\n\n- [ ] Ship it' --title "Launch plan"

# Add the canvas as a channel tab (required on free Slack plans; standard tokens only)
agent-slack canvas create --file ./launch-plan.md --channel "project-launch"

When multiple workspaces are configured, callers can use the standard --workspace <url-or-unique-substring> selector. Channel names go through the same ambiguity checks and name-to-ID resolution used by the rest of the CLI.

Validation and failure behavior

  • missing --file/--markdown is rejected before authentication
  • supplying both source options is rejected before authentication
  • whitespace-only Markdown is rejected
  • file read failures include the source path and underlying error
  • the Markdown bytes read from a file or supplied inline are preserved in the API request
  • a Slack success response without a canvas/file ID is treated as an error
  • channel-tab creation with imported browser credentials fails locally with an actionable standard-token requirement

Documentation

Kept all shipped agent guidance in sync with the implementation:

  • updated the README feature list, command map, usage examples, output shape, auth requirements, and free-plan note
  • updated skills/agent-slack/SKILL.md common commands and mutation safety guidance
  • updated the bundled command and output references
  • updated llms.txt feature metadata

Testing

Live acceptance testing in stablygroup passed for both supported sources using imported browser credentials:

  • created a canvas from a Markdown file and read it back successfully
  • created a canvas from an inline Markdown blob and read it back successfully
  • sent both canvas links to the requested self-DM and verified delivery

Automated verification:

  • bun test — 265 passed, 0 failed
  • focused canvas/client regression suite — 14 passed, 0 failed
  • bun run typecheck
  • bun run build
  • bun run build:npm
  • bun run lint — 0 errors (10 existing warnings in unrelated files)
  • bun run format:check
  • git diff --check

@nwparker
nwparker merged commit 6366f94 into main Jul 18, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant