Create a blank presentation via feishu-cli slides and upload local images as slide_file media to that presentation; the returned file_token can be directly referenced in the slide XML as <img src="..."> .
feishu-cli: if not yet installed, go to riba2534/feishu-cli to get the installation method.
Scope statement: this skill only covers the two minimal usable actions "create a blank presentation" + "upload media". If you need to do complex slide editing (block insert/replace, etc.) in an existing presentation, the CLI does not currently implement it; please use the official
lark-slidesclient or call the OpenAPI directly instead.
Core concepts
What the two artifacts are
| Command | API called | Artifact | Purpose |
|---|---|---|---|
slides create |
POST /open-apis/slides_ai/v1/xml_presentations |
xml_presentation_id |
ID for all subsequent slides operations (not an ordinary docx token) |
slides media-upload |
POST /open-apis/drive/v1/medias/upload_all (parent_type=slide_file) |
file_token |
Can be placed directly into the slide XML's <img src="..."> |
Key constraints:
slide_fileis the onlyparent_typeaccepted by the slides backend (lark-cli verified:slide_image/slides_image/slides_fileare all rejected)parent_nodemust be passedxml_presentation_id(not a docx token or file_token)- Upload uses single-part
upload_all,does not supportupload_preparemulti-part, so the hard limit per file is 20 MB
XML template format (inside create)
slides create Inside the CLI, --title/--width/--height is assembled into a minimal usable XML template and then POSTed:
<presentation xmlns="http://www.larkoffice.com/sml/2.0" width="960" height="540">
<title>演示文稿标题</title>
</presentation>
The current version does not expose the
--xml-fileparameter to let you pass the entire presentation XML directly—you can only influence this minimal template through--title/--width/--heightIf you need complex initial content, firstcreateto get thexml_presentation_id, then use lark-slides or a future CLI extension.
Prerequisites
- Authentication: by default uses App Token(tenant identity); via
--user-access-tokenorFEISHU_USER_ACCESS_TOKENyou can switch to User Token (User Token is recommended, so you create as an individual and can edit directly in Feishu later) - Permissions:
Command Required scope slides createslides:presentation:createorslides:presentation:write_onlyslides media-uploaddocs:document.media:upload - Pre-check:
feishu-cli auth check --scope "slides:presentation:create docs:document.media:upload"
Command quick reference
1. slides create — create a blank presentation
# 最简用法(默认尺寸 960x540,title="Untitled")
feishu-cli slides create
# 指定标题
feishu-cli slides create --title "Q2 OKR"
# 自定义宽高(像素)
feishu-cli slides create --title "Wide Deck" --width 1920 --height 1080
# JSON 输出(脚本接力时常用,方便 jq 取 xml_presentation_id)
feishu-cli slides create --title "Demo" --output json
# 以用户身份创建(推荐,演示文稿归属个人)
feishu-cli slides create --title "Demo" --user-access-token <u-xxx>
Key parameters:
| Parameter | Description | Default value |
|---|---|---|
--title, -t |
Presentation title | Untitled |
--width |
Slide width (pixels) | 960 |
--height |
Slide height (pixels) | 540 |
--output, -o |
Output format (leave empty = text summary,json = JSON) |
Text summary |
--user-access-token |
Explicitly pass User Token | If not passed, App Token is used |
Division of labor between the two layers of defaults:
--titledefaults to an empty string when the cobra flag is registered,--width/--heightis registered as0(seecmd/slides_create.go:78-80); at runtime, the client layer (internal/client/slides.go:49-58) injects an empty title asUntitled, and injects non-positive dimensions as the standard 16:9960x540. So "not passed" ≠ "passed 0" ≠ "error"; all three ultimately fall through to the same default value.
Returns:
Slides 演示文稿已创建:
xml_presentation_id: <id>
title: Q2 OKR
revision_id: 1
xml_presentation_id is what the subsequent media-upload --presentation-token should be passed as the value.
2. slides media-upload — Upload media to a presentation
# 上传封面图
feishu-cli slides media-upload \
--file ./cover.png \
--presentation-token <xml_presentation_id>
# JSON 输出,方便 jq 接力拿 file_token
feishu-cli slides media-upload \
--file ./cover.png \
--presentation-token <xml_presentation_id> \
--output json
Key parameters:
| Parameter | Description | Required |
|---|---|---|
--file |
Local image path (≤ 20 MB) | Yes |
--presentation-token |
is the target presentation's xml_presentation_id |
Yes |
--output, -o |
output format (leave empty = text summary,json = JSON) |
No |
--user-access-token |
Explicitly pass User Token | No |
Returns:
图片上传成功:
file_token: <token>
file_name: cover.png
size: 123456 bytes
presentation_id: <xml_presentation_id>
提示: 在 slide XML 中可用作 <img src="<token>"/>
Typical workflows
Workflow A: Create + upload a cover image (end to end)
# 1. 创建空白演示文稿
PRES_ID=$(feishu-cli slides create --title "Q2 OKR" --output json | jq -r '.xml_presentation_id')
# 2. 上传封面图,拿到 file_token
FILE_TOKEN=$(feishu-cli slides media-upload \
--file ./cover.png \
--presentation-token "$PRES_ID" \
--output json | jq -r '.file_token')
# 3. 现在 $FILE_TOKEN 可以拼到 slide XML 的 <img src="..."> 里
echo "presentation: $PRES_ID, cover: $FILE_TOKEN"
Workflow B: Batch upload a set of images
PRES_ID=$(feishu-cli slides create --title "Photo Deck" --output json | jq -r '.xml_presentation_id')
for img in ./assets/*.png; do
feishu-cli slides media-upload \
--file "$img" \
--presentation-token "$PRES_ID" \
--output json | jq -r '"\(.file_name) -> \(.file_token)"'
done
When to switch to other tools
| Scenario | Switch to |
|---|---|
| Insert/modify/delete a slide or block in an existing presentation | lark-slides(official CLI) or call the OpenAPI directly at slides_ai/v1/... edit endpoint |
| Pass the entire presentation XML template directly | Not yet exposed --xml-file, wait for CLI extension or call OpenAPI directly |
| Media larger than 20 MB per file | Split into smaller images, or upload directly via the Feishu client |
| Convert markdown / docx into slides | Not supported yet; suggested to convert to docx first and then export via the Feishu client |
| Upload media to an ordinary document (not a presentation) | Use the feishu-cli-drive skill (drive upload) |
Caveats
parent_typeDo not change arbitrarily: hardcoded in the source asslide_file, and verified via lark-cli as the only usable value. Changing it yourself toslide_image/slides_image/slides_filewill be rejected by the server- The 20 MB limit cannot be bypassed:
upload_preparemulti-part endpointdoes not acceptparent_type=slide_file, and the CLI also performs a hard 20 MB check on the client side; anything over will error out locally (no request will be sent) xml_presentation_id≠ docx token: this is an identifier independent to the slides module; do not use it asdocx:document_idordrive:file_tokenUse- User Token vs App Token: default App Token (Bot identity); the presentation is owned by the Bot and ordinary people
cannot see it in the Feishu UI.Recommended to pass
--user-access-tokenso the output belongs to the individual and can be found directly in "My Space" - Image formats: common ones like png/jpg/jpeg/gif/webp, with MIME automatically inferred by
medias/upload_allAuto-infer MIME
Troubleshooting
| Error | Cause | Solution |
|---|---|---|
--file 不能为空 / --presentation-token 不能为空 |
Missing required parameter | Check the command-line parameters |
读取文件失败 / --file 必须是普通文件 |
Wrong path or not a regular file | Check the path; do not pass a symlink to a directory |
文件 X 大小 Y 字节超过 slides 上传限制(20 MB) |
File exceeds 20 MB | Compress / split; the slides backend hard limit cannot be bypassed |
创建 slides 失败: code=99991663, msg=... |
Insufficient scope | auth check --scope "slides:presentation:create" then re- auth login --domain slides --recommend |
创建 slides 失败: HTTP 400, body: ...invalid xml_presentation... |
XML template exception (generally triggered by unescaped characters in the title) | The CLI already performs XML escape; if it still occurs, please file an issue |
Upload reports parent_type invalid or similar |
not using slide_file(e.g., when calling medias/upload_all directly via curl with the wrong one) |
Use the CLI instead of hand-writing curl; the CLI has already locked slide_file |
Reference
- API docs: Feishu Open Platform "Smart Presentation" / "Cloud Docs - Materials"
- Code:
cmd/slides_create.go/cmd/slides_media_upload.go/internal/client/slides.go - Upstream PR:feishu-cli#135