| name | publish-instagram |
| description | 用 Playwright 在 Instagram 發一篇 Feed 含圖貼文(非 Story)。 |
共通規則見 CLAUDE.md「共通行為規則」章節,本檔只描述 IG 特有的步驟。
每步結束都要呼叫 scripts/log-click.sh(格式見 CLAUDE.md「Click recording」)。
Input
caption:貼文文字
hashtags:list of string(IG 上限 30 個)
local_image_path:本地圖檔絕對路徑
draft_id / run_id:caller(/publish-now)傳入
Output
{ "post_url": "https://..." }
Step ID 鎖定表(log --step 值必須一字不差用以下、不准自取)
| step_id | 必要 | 用途 |
|---|
1_navigate_home | 必 | browser_navigate → https://www.instagram.com/ |
2_click_create_sidebar | 必 | 點左側 sidebar「Create / 建立」 |
3_click_post_option | 必 | 點「Post / 貼文」 |
4_file_upload | 必 | 上傳檔案 |
4b_dismiss_reels_info | 條件 | 直式影片時 IG 跳「Now you can share videos as reels」 dialog → 點「OK」(圖片無此 dialog) |
5_click_next_crop | 必 | 「Next」跳過裁切 |
6_click_next_filter | 必 | 「Next」跳過篩選器 |
7_type_caption | 必 | caption 輸入 |
8_click_share | 必 | 點「Share」 |
9_wait_home_return | 必 | 等「Your post/reel has been shared」確認文字 |
10_extract_post_url | 必 | 抓最新貼文 URL |
為什麼鎖定:跨平台規則見 OPERATING_RULES §9。簡言之,click-log 統計分析需要 step_id 穩定才看得出 pattern。
「條件」步驟若當下不適用,仍要 log 一筆 --ok true --ms 0 --args '{"reason":"skipped_no_dialog"}' 占位,不要省略。
流程細節
1_navigate_home — browser_navigate → https://www.instagram.com/
2_click_create_sidebar — 點左側 sidebar「Create / 建立」
3_click_post_option — 點「Post / 貼文」
4_file_upload — browser_file_upload 傳 local_image_path
4b_dismiss_reels_info — 直式影片會跳 reels 提示 dialog,點「OK」;圖片無此 dialog → log skip
5_click_next_crop — 「Next / 下一步」(跳過裁切)
6_click_next_filter — 「Next / 下一步」(跳過篩選器)
7_type_caption — caption 框輸入 caption + "\n.\n.\n.\n" + hashtags.join(" ")(IG 慣例:tags 與正文用 3 行點隔開)
8_click_share — 點「Share / 分享」
9_wait_home_return — 等「Your post/reel has been shared」確認文字
10_extract_post_url — 讀 config/brand.yaml.socials.instagram.url、browser_navigate 過去抓最新貼文 URL
Dry-run 模式
當 caller 傳入 mode: dry_run:
- 跑 step 1 ~ step 7(含
7_type_caption)正常完成
- 跳過 step 8
8_click_share — 不真的發出去
- 跳過 step 9 / 10
- 收尾:
- 用
browser_press_key Escape 或點右上 X 關閉 New Post composer
- 若跳「捨棄變更?」確認 dialog → 點「捨棄 / Discard」
browser_close
- 回
{"status": "dry_run_ok", "stages_passed": ["1_navigate_home", ..., "7_type_caption"], "abort_at_step": "8_click_share"}
- 若中途某步抓不到按鈕或 dialog 異常 → 回
{"status": "dry_run_failed", "step_failed": "<step>", "error": "<原因>"}
dry-run 不寫 click-log(跟真實 publish 區分、避免污染分析資料)。也不寫 reports/posts/ 報告。
IG 特有的坑
以下是已知 case,非 exhaustive list。中間步驟遇到沒列出的 dialog / 元素 drift / 載入慢 → 自己 reasoning 解(OPERATING_RULES §4「過程雜訊 vs 終點驗收」),不要 surface 給使用者。只有終點驗收(post URL、登入態、2FA gate、素材)才老實回 error。
影片副檔名 .MOV → .mp4 必先改
TG 上傳的影片(特別是 iPhone 來源的)檔名常以 .MOV 結尾,但容器其實已經是 MP4 v2(TG 上傳時自動轉碼)。IG web validator 依副檔名判斷格式、會在 file_upload 階段擋 .MOV、回「This file is not supported」。
- 收到 video 路徑、副檔名是
.MOV(任何大小寫) → 在進 publish 流程前 cp foo.MOV foo.mp4、用 .mp4 路徑送進 file_upload
- 不需要重編碼、只是改副檔名
- 不要刪原檔(素材會被多次重用)
- 已驗證:2026-05-01 用此方式從失敗變成功
風控(屬終點驗收)
- IG 對自動化敏感、容易被風控
- 卡登入頁 / 卡 2FA → 屬終點驗收(LLM 沒辦法替使用者輸密碼 / 收簡訊)→ log 對應 step
--ok false --error "login or 2FA gate"、回 { "error": "login expired, run /first-time-login" }、不要重試
- 偶爾跳 cookie / age confirm / promotion banner 之類的非關鍵 dialog → 過程雜訊、自己關掉、不報
Reel vs Feed
- 這個 skill 預設處理 Feed 貼文(圖片 carousel / 單圖 / 短影音都從 + New Post 進)
- IG web 自動偵測直式影片並走 Reel 流程(cover / trim / sound 三鈕,沒有音樂搜尋 UI — 桌面版限制)
- 要指定配樂只能手機 IG app 後製(
docs/WARNINGS.md 有記)— 不要嘗試在 web 找音樂選項
- 已驗證:2026-05-03