[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6MWAPDM8H8T2YJ0ATZ2R4H5":3,"skill-same:01M6MWAPDM8H8T2YJ0ATZ2R4H5":83},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":30,"publishedAt":51,"linkOnly":52,"markdownContent":53,"markdownBody":54,"frontMatter":55,"refName":56,"commitSha":57,"skillDirectory":58,"forksCount":59,"repositoryHtmlUrl":60,"repositoryHomepageUrl":6,"ownerHtmlUrl":61,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":62,"install":63,"resources":76},"01M6MWAPDM8H8T2YJ0ATZ2R4H5","forbotsake-publish",null,"Stage 8: SHIP. Two modes: POST (auto-post via Claude for Chrome) or COPY\n(format for copy-paste). Handles X\u002FTwitter threads, LinkedIn posts, blog posts,\nand more. Logs everything for retrospective analysis.\nFor auto-posting, the user needs the Claude for Chrome extension installed.\nWithout it, the skill falls back to COPY mode automatically.\nUse when: \"publish this\", \"format for twitter\", \"post to X\", \"ship this content\",\n\"format for blog\", \"send this email\", \"ready to publish\", \"auto-post\",\n\"post this to X\", \"publish to LinkedIn\".\nProactively invoke when the user has content in content\u002F and says they want to ship it.","forbotsake\u002Fforbotsake","forbotsake","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F273708741?v=4","01M6MW9A04DY7WQBA8YF96SVJE","01M6MW9A47HYRVBBQ642740E75",5,"MIT","https:\u002F\u002Fgithub.com\u002Fforbotsake\u002Fforbotsake\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fforbotsake-publish\u002FSKILL.md",[17,22,25],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000005","邮件与沟通","SCENARIO","使用场景",{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":26,"categoryName":27,"taxonomyType":28,"taxonomyTypeDesc":29},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50],"forbotsake publish","publish","back","send","for","mode","paste","threads","posts","posting","ship it","logs","chrome extension","ready","auto","twitter","retrospective analysis","ship","analysis","email","2026-11-10 10:12:30",false,"---\nname: forbotsake-publish\ndescription: >\n  Stage 8: SHIP. Two modes: POST (auto-post via Claude for Chrome) or COPY\n\n  (format for copy-paste). Handles X\u002FTwitter threads, LinkedIn posts, blog\n  posts,\n\n  and more. Logs everything for retrospective analysis.\n\n  For auto-posting, the user needs the Claude for Chrome extension installed.\n\n  Without it, the skill falls back to COPY mode automatically.\n\n  Use when: \"publish this\", \"format for twitter\", \"post to X\", \"ship this\n  content\",\n\n  \"format for blog\", \"send this email\", \"ready to publish\", \"auto-post\",\n\n  \"post this to X\", \"publish to LinkedIn\".\n\n  Proactively invoke when the user has content in content\u002F and says they want to\n  ship it.\n---\n\n# \u002Fforbotsake-publish\n\nFrom draft to published. Format, post, log.\n\n## Preamble\n\n```bash\nFORBOTSAKE_HOME=\"${FORBOTSAKE_HOME:-$HOME\u002F.forbotsake}\"\nmkdir -p \"$FORBOTSAKE_HOME\"\n\n# Discover forbotsake install directory\n_FBS_ROOT=\"\"\nfor _FBS_CANDIDATE in \"$HOME\u002F.codex\u002Fskills\u002Fforbotsake\" \"$HOME\u002F.agents\u002Fskills\u002Fforbotsake\"; do\n  [ -d \"$_FBS_CANDIDATE\" ] && _FBS_ROOT=\"$_FBS_CANDIDATE\" && break\ndone\nif [ -z \"$_FBS_ROOT\" ]; then\n  echo \"WARNING: forbotsake not found. Install: bash \u003C(curl -fsSL https:\u002F\u002Fraw.githubusercontent.com\u002Fforbotsake\u002Fforbotsake\u002Fmain\u002Fbin\u002Finstall.sh)\"\nfi\n\n# Check for updates\n_UPD=\"\"\n[ -n \"$_FBS_ROOT\" ] && [ -x \"$_FBS_ROOT\u002Fbin\u002Fforbotsake-update-check\" ] && _UPD=$(\"$_FBS_ROOT\u002Fbin\u002Fforbotsake-update-check\" 2>\u002Fdev\u002Fnull || true)\n[ -n \"$_UPD\" ] && echo \"$_UPD\" || true\n_BRANCH=$(git branch --show-current 2>\u002Fdev\u002Fnull || echo \"unknown\")\necho \"BRANCH: $_BRANCH\"\n```\n\n```bash\n\n# Orchestrated mode (invoked by forbotsake-go, propagated via file flag)\n_ORCH_FILE=\"${FORBOTSAKE_HOME:-$HOME\u002F.forbotsake}\u002Forchestrated-$(basename \"$(git rev-parse --show-toplevel 2>\u002Fdev\u002Fnull || pwd)\")\"\nFORBOTSAKE_ORCHESTRATED=$(cat \"$_ORCH_FILE\" 2>\u002Fdev\u002Fnull || echo 0)\necho \"ORCHESTRATED: $FORBOTSAKE_ORCHESTRATED\"\n\n# Check for strategy.md\nif [ -f strategy.md ]; then\n  echo \"STRATEGY: yes\"\nelse\n  echo \"STRATEGY: no\"\n  echo \"WARNING: No strategy.md found. Run \u002Fforbotsake-marketing-start first.\"\nfi\n\n# Check for content directory\nif [ -d content\u002F ]; then\n  echo \"CONTENT_DIR: yes\"\n  ls -1 content\u002F 2>\u002Fdev\u002Fnull | head -20\nelse\n  echo \"CONTENT_DIR: no\"\nfi\n\n# Check for published log\nif [ -f published-log.md ]; then\n  echo \"PUBLISHED_LOG: yes\"\n  tail -5 published-log.md\nelse\n  echo \"PUBLISHED_LOG: no\"\nfi\n```\n\nIf output shows `UPGRADE_AVAILABLE \u003Cold> \u003Cnew>`: read the forbotsake-upgrade SKILL.md\nat `$_FBS_ROOT\u002Fforbotsake-upgrade\u002FSKILL.md` (where `_FBS_ROOT` is the variable already\nresolved in the preamble bash above) and follow the \"Inline upgrade flow\" section **Step 1\nonly**. If Step 1 results in \"Yes\" or \"Always\" (proceed with upgrade), continue through\nSteps 2-7 of the inline flow. If Step 1 results in \"Not now\" or \"Never\" (declined),\nskip Steps 2-7 entirely and continue with this skill immediately.\n\nIf output shows `JUST_UPGRADED \u003Cold> \u003Cnew>`: tell user\n\"Running forbotsake v{new} (just updated from v{old})!\" and continue.\n\nIf `STRATEGY` is `no`: \"No strategy.md found. You need positioning and channel strategy before publishing. Run `\u002Fforbotsake-marketing-start` first.\"\nStop here unless user insists.\n\nIf `CONTENT_DIR` is `no`: \"No content\u002F directory found. Run `\u002Fforbotsake-create` to write your first piece, or point me to the content you want to publish.\"\nAsk the user directly in conversation to let the user provide content manually if they prefer.\n\n## Chrome Detection\n\nAfter the preamble checks, detect whether Claude for Chrome browser tools are available. Try calling `mcp__claude-in-chrome__tabs_context_mcp` to check if the Chrome extension is connected. If it responds successfully, set CHROME_AVAILABLE to yes. If it errors or is not available, set CHROME_AVAILABLE to no.\n\nIf CHROME_AVAILABLE is yes: the user can choose POST mode (auto-post via Chrome) or COPY mode.\n\nIf CHROME_AVAILABLE is no: silently default to COPY mode. Mention once: \"Auto-posting available with the Claude for Chrome extension. Using copy-paste mode.\"\n\n## Phase 1: Select Content and Platform\n\n**Orchestrated mode (`ORCHESTRATED` is `1`):**\n- Auto-select content files: format ALL content files with `status: reviewed`, `status: revised`, or `status: reviewed-override` in frontmatter\n- Auto-select platform from each file's `channel:` frontmatter field\n- If a file has no channel specified, use the highest-scored channel from strategy.md\n- Skip the content\u002Fplatform selection direct conversation with the user\n- In Phase 4: skip \"Want me to format this for another platform too?\" — just format and log\n- After logging to published-log.md, update each published content file's frontmatter from `status: reviewed` (or `revised`\u002F`reviewed-override`) to `status: published`. This prevents re-publish loops when forbotsake-go runs again.\n- Skip Phase 5 (Next Steps) — the orchestrator handles what's next\n\n**Interactive mode (`ORCHESTRATED` is `0`):**\n\nRead `strategy.md` to understand the channel strategy and ICP.\n\nRead all files in `content\u002F` to see what's available. Check each file's frontmatter for `status` field. Files with `status: published` in the log should be noted as already published.\n\nAsk the user directly in conversation:\n\n> \"Here's what I found in your content\u002F directory:\n>\n> {list each file with a one-line summary and status}\n>\n> Which piece do you want to publish? And which platform?\n>\n> **Auto-post** (I post for you via Chrome):\n> - **X\u002FTwitter** (threads + single tweets)\n> - **LinkedIn** (posts)\n>\n> **Copy-paste + open browser** (I format it, open the compose page, you paste):\n> - **Blog** (Ghost, WordPress, Dev.to, Medium, Substack)\n> - **Reddit**\n> - **Hacker News**\n> - **Product Hunt**\n>\n> **Copy-paste only:**\n> - **Email** (formatted for your ESP)\n>\n> **CLI:**\n> - **GitHub** (PRs via `gh` CLI)\n>\n> Pick a content piece and a platform.\"\n\nIf CHROME_AVAILABLE is no, present all platforms as \"Copy-paste\" mode only. Do not show the Auto-post tier.\n\nIf the user says \"all\" or \"publish everything\", loop through each unpublished content file and process them sequentially. Between posts to the same platform, wait 30-60 seconds. Maximum 5 posts to the same platform per session to avoid triggering anti-automation measures.\n\n### Mode Selection\n\nIf CHROME_AVAILABLE is yes AND the selected platform is X\u002FTwitter or LinkedIn, ask the user directly in conversation:\n\n> \"How do you want to publish to {platform}?\n> A) **POST** — I'll post it for you right now via Chrome\n> B) **COPY** — just give me the formatted text\"\n\nFor blog platforms, Reddit, HN, and Product Hunt: if Chrome is available, offer to open the platform's compose page in a new Chrome tab after formatting. This is a \"COPY + deep link\" flow — you format the content, open the compose URL, and the user pastes it in.\n\nFor Email and GitHub: always COPY mode (email ESPs vary too much for automation; GitHub uses `gh` CLI).\n\n## Phase 1.5: Visual Asset Detection\n\nFor each selected content file, check if visual assets exist alongside it:\n\n```bash\n# For a content file like content\u002F2026-04-07-x-launch-thread.md\n# Look for: content\u002F2026-04-07-x-launch-thread-visual-*.png or *.mp4\nls content\u002F*-visual-*.{png,jpg,mp4} 2>\u002Fdev\u002Fnull\n```\n\nAlso read the content file's frontmatter for visual metadata:\n- `visual_treatment`: none\u002Ftext-card\u002Fai-image\u002Fvideo\n- `visual_status`: generated\u002Ffailed\u002Fpending\u002Fskipped\n- `visual_alt`: accessibility description\n\n**If visual assets exist** (`visual_status: generated`):\n- Note which files are available and their paths\n- These will be attached during posting (Phase 4)\n\n**If visual_treatment is not `none` but no visual file exists** (`visual_status: failed\u002Fpending\u002Fskipped`):\n- **Interactive mode:** Warn the user: \"This {channel} post has visual treatment '{visual_treatment}' but no image was generated. Options: A) Publish text-only B) Generate the image now C) Cancel\"\n- **Orchestrated mode:** Publish text-only, log the missing visual\n\n**If visual_treatment is `none`:** No visual handling needed, proceed normally.\n\n## Phase 2: Format for Platform\n\n### X\u002FTwitter Thread Format\n\nRead the knowledge framework for thread structure:\n```bash\n_SKILL_DIR=$(dirname \"$(find $HOME\u002F.codex\u002Fskills -path \"*\u002Fforbotsake-publish\u002FSKILL.md\" -type f 2>\u002Fdev\u002Fnull | head -1)\")\necho \"SKILL_DIR: $_SKILL_DIR\"\n```\n\nRead `$_SKILL_DIR\u002F..\u002Fknowledge\u002Fframeworks\u002Fcontent-strategy.md` for X thread format guidelines.\n\nFormat the content as a numbered thread following these rules:\n\n1. **Tweet 1 (The Hook):** Must stop the scroll. Lead with the most surprising, contrarian, or specific claim. No preamble. No \"I've been thinking about...\" Start with the insight. Must be under 280 characters.\n\n2. **Tweets 2-N (The Body):** One idea per tweet. Each tweet must stand alone if someone screenshots it. Use line breaks for readability. Keep each under 280 characters.\n\n3. **Final Tweet (The CTA):** What should the reader do? Follow, reply, check out the product, share? Be specific. Include the link if there is one.\n\nOutput format:\n```\n---\nTHREAD: {title}\nPlatform: X\u002FTwitter\nTweets: {count}\nCharacter counts: verified\n---\n\n1\u002F {hook tweet}\n[{character count}\u002F280]\n\n2\u002F {body tweet}\n[{character count}\u002F280]\n\n...\n\n{N}\u002F {CTA tweet}\n[{character count}\u002F280]\n```\n\nVerify every tweet is under 280 characters. If any exceeds the limit, split or rewrite it. Do NOT deliver a thread with tweets over 280 characters.\n\n### Blog Post Format\n\nFormat with full SEO structure:\n\n```\n---\nBLOG POST: {title}\nPlatform: Blog\nWord count: {count}\nReading time: {X} min\n---\n\n## SEO Meta\n- **Title tag** (under 60 chars): {title}\n- **Meta description** (under 155 chars): {description}\n- **URL slug:** {slug}\n- **Target keyword:** {keyword}\n- **Secondary keywords:** {list}\n\n## Headline Options\n1. {headline option 1 - benefit-focused}\n2. {headline option 2 - curiosity-driven}\n3. {headline option 3 - specific\u002Fnumbered}\n\n## Featured Image Suggestions\n- {description of image 1 - what to create or find}\n- {description of image 2 - alternative option}\n\n## Post Body\n\n{formatted blog post with H2\u002FH3 headers, short paragraphs, bold key phrases}\n\n## Internal Links\n- {suggest where to link to product, other content, etc.}\n```\n\n### Email Format\n\nFormat with multiple subject line options and clear structure:\n\n```\n---\nEMAIL: {title}\nPlatform: Email\nWord count: {count}\n---\n\n## Subject Line Options\n1. {subject line 1} [{character count} chars]\n2. {subject line 2} [{character count} chars]\n3. {subject line 3} [{character count} chars]\n\n## Preview Text\n{the text that shows after the subject in inbox, under 90 chars}\n\n## Email Body\n\n{formatted email - short paragraphs, conversational, one clear ask}\n\n## CTA\n- **Primary CTA:** {button text} -> {URL or action}\n- **Secondary CTA:** {text link or PS line}\n\n## Send Time Suggestion\n{best time to send based on audience from strategy.md}\n```\n\n### LinkedIn Post Format\n\nFormat for LinkedIn's algorithm and audience:\n\n```\n---\nLINKEDIN POST: {title}\nPlatform: LinkedIn\nCharacter count: {count}\u002F3000\n---\n\n{hook line - must work as the \"see more\" preview}\n\n{body - short paragraphs, line breaks between each, no walls of text}\n\n{CTA or question to drive comments}\n\n{3-5 relevant hashtags}\n```\n\n### Other Platform\n\nAsk the user directly in conversation to understand the platform's constraints (character limits, format, audience norms), then format accordingly.\n\n## Phase 3: Publish Kill Switch + Quality Check\n\n**Skip the kill switch (3a) if `FORBOTSAKE_FAST` env var is `1`.** Print: \"FORBOTSAKE_FAST=1: skipping publish kill switch.\" Jump to 3b.\n\nThis is the last gate before content goes public. Not a deep review (that happened\nin \u002Fforbotsake-content-check). This is a final sanity check: \"would I be embarrassed?\"\n\n### Phase 3a: Kill Switch (Adversarial)\n\nRead the banned patterns files:\n\n```bash\nFORBOTSAKE_HOME=\"${FORBOTSAKE_HOME:-$HOME\u002F.forbotsake}\"\n_SKILL_DIR=$(dirname \"$(find $HOME\u002F.codex\u002Fskills -path \"*\u002Fforbotsake-marketing-start\u002FSKILL.md\" -type f 2>\u002Fdev\u002Fnull | head -1)\" 2>\u002Fdev\u002Fnull)\n_FBS_ROOT=$(cd \"${_SKILL_DIR}\u002F..\" 2>\u002Fdev\u002Fnull && pwd || true)\n[ -n \"$_FBS_ROOT\" ] && [ -f \"$_FBS_ROOT\u002Fknowledge\u002Fbanned-patterns-defaults.md\" ] && echo \"DEFAULTS: found\" || echo \"DEFAULTS: not_found\"\n[ -f \"$FORBOTSAKE_HOME\u002Fbanned-patterns.md\" ] && echo \"USER_PATTERNS: found\" || echo \"USER_PATTERNS: none\"\n```\n\nRead the banned patterns file(s). Then scan the formatted content for:\n\n1. **Embarrassment test:** Read the final formatted content as if you're the ICP seeing it\n   for the first time. Would you show this to your smartest friend? Any sentence that\n   makes you cringe?\n\n2. **Factual claims:** Any claims that could be verifiably wrong? Specific numbers,\n   statistics, or comparisons that the founder hasn't verified?\n\n3. **AI tell scan:** Check for patterns from the banned patterns files. Count matches.\n   Each pattern match adds to a score. This is a contributing signal, not an automatic\n   fail. 3+ pattern matches across the piece = HOLD.\n\n4. **Platform fit:** Does the formatted version look right for the platform?\n   Character limits respected? Thread structure correct? Links formatted correctly?\n\n**Scoring:** Each dimension contributes to a GO\u002FHOLD verdict.\n- Any factual claim issue = HOLD\n- Embarrassment test fails = HOLD\n- 3+ banned pattern matches = HOLD\n- Platform fit issues = fix inline, don't HOLD\n\n**If GO:** Print \"Publish Kill Switch: GO. Content cleared for publishing.\" Continue to Phase 3b.\n\n**If HOLD:** This ALWAYS requires explicit user confirmation, even in orchestrated mode.\n\n> \"**Publish Kill Switch: HOLD**\n>\n> Last-gate check before this goes public:\n> {for each issue:}\n> - **{dimension}:** {specific concern}\n>\n> This content has not been published yet. Your call.\"\n\nAsk the user directly in conversation:\nA) Publish anyway (I've reviewed the concerns)\nB) Go back and fix it\n\nIf A: log override to metrics, continue.\nIf B: stop the publish flow. User returns to \u002Fforbotsake-content-check or manual editing.\n\nLog result:\n```bash\nFORBOTSAKE_HOME=\"${FORBOTSAKE_HOME:-$HOME\u002F.forbotsake}\"\nmkdir -p \"$FORBOTSAKE_HOME\"\necho '{\"gate\":\"publish\",\"ts\":\"'\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"'\",\"result\":\"RESULT\",\"content_file\":\"FILENAME\",\"override\":BOOL}' >> \"$FORBOTSAKE_HOME\u002Freview-metrics.jsonl\" 2>\u002Fdev\u002Fnull || true\n```\n\n### Phase 3b: Quality Check (Structural)\n\nBefore delivering the formatted content, verify:\n\n1. **Character limits:** Every tweet under 280. Blog title under 60. Email subjects tested for length.\n2. **ICP alignment:** Does this speak to the person defined in strategy.md? Would they stop scrolling?\n3. **CTA present:** Every piece has a clear next action for the reader.\n4. **No jargon leak:** The content uses the reader's language, not the builder's.\n5. **Link placeholders:** If URLs are needed, mark them clearly as `[YOUR_LINK_HERE]` so nothing is missed.\n\nIf any check fails, fix it before presenting to the user.\n\n## Phase 4: Deliver or Post\n\nThis phase splits based on the mode selected in Phase 1.\n\n### COPY Mode (all platforms)\n\nPresent the formatted content to the user with:\n\n> \"Here's your {platform}-ready content. Copy-paste ready.\n>\n> {formatted content}\n>\n> {If visual asset exists: \"**Attach this image:** `{path to visual file}`\n> Alt text: {visual_alt from frontmatter}\"}\n>\n> {If visual_treatment is video and video file exists: \"**Attach this video:** `{path to video file}`\"}\n>\n> Before you post, double-check:\n> - [ ] Links are correct\n> - [ ] Handle\u002Fusername is right\n> - [ ] {If visual: \"Image\u002Fvideo is attached\"}\n> - [ ] Timing is good (see send time suggestion if applicable)\n>\n> Want me to format this for another platform too?\"\n\nFor blog platforms, Reddit, HN, and Product Hunt: if Chrome is available, also open the platform's compose page in a new tab using `mcp__claude-in-chrome__tabs_create_mcp` so the user can paste directly. Tell the user: \"I've opened {platform} in a new tab. Paste your content there.\"\n\nSkip to Phase 5 (Log).\n\n### POST Mode (X\u002FTwitter and LinkedIn only)\n\nPOST mode automates the entire posting flow via Claude for Chrome. It works best for X and LinkedIn, which have stable compose UIs. Other platforms may have lower reliability. COPY mode always works as a fallback.\n\n#### Step 4a: Account Identity Preflight\n\nBefore posting anything, verify the logged-in account:\n\n1. Use `mcp__claude-in-chrome__tabs_create_mcp` to open the platform's home page (x.com\u002Fhome for X, linkedin.com\u002Ffeed for LinkedIn).\n2. Use `mcp__claude-in-chrome__read_page` or `mcp__claude-in-chrome__get_page_text` to find the current username\u002Fhandle on the page.\n3. Ask the user directly in conversation: \"I see you're logged in as {handle} on {platform}. Is that the right account to post from?\"\n4. If user confirms, proceed. If not, tell them to switch accounts in Chrome and try again, or use COPY mode.\n\nIf the page shows a login wall instead of the home feed, the user is not logged in. Fall back to COPY mode: \"Looks like you're not logged into {platform} in Chrome. Here's the formatted text to copy-paste instead.\"\n\n#### Step 4b: Navigate to Compose\n\nRead the publishing automation knowledge framework for platform-specific instructions:\n```bash\n_SKILL_DIR=$(dirname \"$(find $HOME\u002F.codex\u002Fskills -path \"*\u002Fforbotsake-publish\u002FSKILL.md\" -type f 2>\u002Fdev\u002Fnull | head -1)\")\necho \"SKILL_DIR: $_SKILL_DIR\"\n```\n\nRead `$_SKILL_DIR\u002F..\u002Fknowledge\u002Fframeworks\u002Fpublishing-automation.md` for the platform-specific posting flow. If this file does not exist, use the inline instructions below.\n\n**For X\u002FTwitter:**\n1. Use `mcp__claude-in-chrome__navigate` to go to `https:\u002F\u002Fx.com\u002Fcompose\u002Fpost`\n2. Wait for the compose area to load\n3. Use `mcp__claude-in-chrome__read_page` to verify the compose UI is present\n\n**For LinkedIn:**\n1. Use `mcp__claude-in-chrome__navigate` to go to `https:\u002F\u002Flinkedin.com\u002Ffeed`\n2. Use `mcp__claude-in-chrome__find` to locate the \"Start a post\" button\n3. Use `mcp__claude-in-chrome__computer` to click it\n4. Wait for the compose modal to appear\n\nIf navigation fails or the compose UI is not found:\n- **What happened:** \"Could not find the compose area on {platform}.\"\n- **Why:** \"The page may have changed, or you may not be logged in.\"\n- **Fix:** \"Try refreshing the page in Chrome, or use COPY mode instead.\"\nFall back to COPY mode and deliver the formatted text.\n\n#### Step 4c: Fill Content\n\n**X\u002FTwitter single tweet:**\n1. **If visual asset exists:** Attach image FIRST before typing text.\n   - Use `mcp__claude-in-chrome__upload_image` with the visual file path to upload the image to the compose area.\n   - If `upload_image` tool is not available: use `mcp__claude-in-chrome__computer` to click the media icon (camera\u002Fimage button), then try attaching via the file dialog. If that fails, fall back to COPY mode with the image path noted.\n   - Wait for the image preview to appear in the compose area before continuing.\n2. Use `mcp__claude-in-chrome__computer` to click the compose textarea\n3. Use `mcp__claude-in-chrome__computer` to type the tweet text\n4. Take a screenshot: `screencapture -x \u002Ftmp\u002Fforbotsake-pre-post-$(date +%s).png` and then use the Read tool to show it to the user. If screencapture fails (non-macOS), skip the screenshot and continue.\n\n**X\u002FTwitter thread:**\n1. **If visual asset exists:** Attach image to tweet 1 (hero placement) using `mcp__claude-in-chrome__upload_image` BEFORE typing text. If `visual_count` > 1, attach subsequent images to their corresponding tweets.\n2. Use `mcp__claude-in-chrome__computer` to click the compose textarea\n3. Type tweet 1 text\n3. Look for the thread \"+\" button (usually near the bottom of the compose area) and click it\n4. A new tweet textarea appears. Type tweet 2 text.\n5. Repeat for all tweets in the thread.\n6. Take a screenshot: `screencapture -x \u002Ftmp\u002Fforbotsake-pre-post-$(date +%s).png` and use the Read tool to show it.\n\n**Compose-time failure recovery:** If thread composing fails (e.g., the \"+\" button is not found after tweet N):\n1. Immediately stop.\n2. The thread has NOT been posted yet (it's still in the compose UI).\n3. Show the user: \"Could not add tweet {N+1} to the thread. Here's the full thread as copy-paste instead.\"\n4. Fall back to COPY mode. Do not log as PARTIAL (nothing was published).\n\n**Post-time failure recovery:** If the \"Post all\" button is clicked but the thread only partially appears (platform error):\n1. Use `mcp__claude-in-chrome__read_page` to check what was actually published.\n2. If partial content is live, capture the URL.\n3. Log to published-log.md as PARTIAL (see Phase 5).\n4. Show the user: \"Thread partially posted ({N}\u002F{total} tweets). Here are the remaining tweets to post manually: {remaining tweets formatted}.\"\n\n**LinkedIn post:**\n1. **If visual asset exists:** Attach image FIRST.\n   - Use `mcp__claude-in-chrome__upload_image` to upload the image into the LinkedIn compose modal.\n   - If it's a carousel (multiple text-cards), upload as a PDF document using the document attachment option.\n   - Wait for the image\u002Fdocument preview to appear.\n2. Use `mcp__claude-in-chrome__computer` to click the compose area in the modal\n3. Type the post content\n4. Take a screenshot using `screencapture` as pre-post evidence\n\n#### Step 4d: Confirm and Post\n\nBefore clicking Post, show the user a screenshot of the filled compose area and ask for confirmation:\n\n> \"Here's what's ready to post on {platform}. {screenshot}\n>\n> Ready to publish?\"\n\nAsk the user directly in conversation with options: A) Post it, B) Edit first (switch to COPY mode), C) Cancel.\n\nIf A (Post):\n1. Use `mcp__claude-in-chrome__computer` to click the Post\u002FPublish button.\n2. Wait 3 seconds for the platform to process.\n\nIf the user specifies a time (e.g., \"schedule for Monday 10am PT\"):\n1. Instead of clicking Post, look for the schedule button (calendar\u002Fclock icon near the Post button).\n2. Click it to open the scheduling UI.\n3. Set the date and time using the platform's native scheduling interface.\n4. Confirm the schedule.\n5. Log as POST in Phase 5 with a \"Scheduled for: {date\u002Ftime}\" note.\n\n#### Step 4e: Verify and Capture\n\nAfter posting:\n1. Use `mcp__claude-in-chrome__read_page` or `mcp__claude-in-chrome__get_page_text` to read the current page.\n2. Check that the URL has changed to include a post ID (e.g., `x.com\u002F{handle}\u002Fstatus\u002F{id}`).\n3. Verify that key phrases from the source content appear on the published page. Note: platforms mangle URLs (t.co links on X) and may convert special characters. Compare the main text content, not URLs or formatting.\n4. Take a screenshot: `screencapture -x \u002Ftmp\u002Fforbotsake-published-$(date +%s).png` and use the Read tool to show it.\n5. Extract the post URL.\n\nIf URL capture fails (some platforms don't redirect immediately):\nTell the user: \"Posted successfully. The URL didn't load yet. Paste it into published-log.md when you see it.\"\n\nIf content verification fails (published content doesn't match source):\nWarn: \"Published content may not match source. Please verify the post on {platform}.\"\n\nIf any step in Phase 4 fails, fall back to COPY mode and log the failure. Every error message must include:\n1. **What happened** (specific failure)\n2. **Why** (likely cause)\n3. **Fix** (actionable next step)\n\n## Phase 5: Log\n\nAppend to `published-log.md` in the project root. Create the file if it doesn't exist.\n\n### Successful POST entry:\n```markdown\n## {date} - {platform}\n\n- **Content:** {title or first line}\n- **Source file:** {path to content file}\n- **Format:** {thread\u002Fblog\u002Femail\u002Flinkedin\u002Fother}\n- **Mode:** POST\n- **Link:** {captured URL}\n- **Visual:** {visual_treatment} via {visual_provider} — {path to visual file or \"none\"}\n- **Notes:** {any relevant context}\n\n---\n```\n\n### Autonomous POST entry (cron\u002Ftick mode):\n```markdown\n## {date} - {platform} (AUTO)\n\n- **Content:** {title or first line}\n- **Source file:** {path to content file}\n- **Format:** {thread\u002Fblog\u002Femail\u002Flinkedin\u002Fother}\n- **Mode:** POST (autonomous\u002Fcron)\n- **Link:** {captured URL}\n- **Scheduled:** {ISO 8601 from content-calendar.md}\n- **Posted:** {ISO 8601 actual post time}\n- **Result:** success\n- **Notes:** Auto-posted by forbotsake-cron\n\n---\n```\n\n### Autonomous FAILED entry (cron\u002Ftick mode):\n```markdown\n## {date} - {platform} (AUTO\u002FFAILED)\n\n- **Content:** {title or first line}\n- **Source file:** {path to content file}\n- **Mode:** POST (autonomous\u002Fcron)\n- **Result:** failed\n- **Failure reason:** {specific error}\n- **Notes:** Content status set to `failed`. Set back to `reviewed` to retry.\n\n---\n```\n\n### MISSED entry (catch-up skip policy):\n```markdown\n## {date} - {platform} (MISSED)\n\n- **Content:** {title or first line}\n- **Source file:** {path to content file}\n- **Scheduled:** {ISO 8601 from content-calendar.md}\n- **Result:** missed\n- **Reason:** Laptop was asleep, catch-up policy: skip\n- **Notes:** Content remains `reviewed`. Manually post or reschedule.\n\n---\n```\n\n### Successful COPY entry:\n```markdown\n## {date} - {platform}\n\n- **Content:** {title or first line}\n- **Source file:** {path to content file}\n- **Format:** {thread\u002Fblog\u002Femail\u002Flinkedin\u002Fother}\n- **Mode:** COPY\n- **Link:** pending\n- **Visual:** {visual_treatment} via {visual_provider} — {path to visual file or \"none\"}\n- **Notes:** Copy-paste delivered. Update link after posting. {If visual exists: \"Attach image: {path}\"}\n\n---\n```\n\n### Partial publish entry (thread interrupted):\n```markdown\n## {date} - {platform} (PARTIAL)\n\n- **Content:** {title or first line}\n- **Source file:** {path to content file}\n- **Format:** thread\n- **Mode:** POST (partial)\n- **Link:** {URL of first tweet if captured}\n- **Posted:** {N}\u002F{total} tweets\n- **Notes:** Thread posting interrupted after tweet {N}. Remaining tweets delivered as copy-paste.\n\n---\n```\n\n### Failed POST entry (fell back to COPY):\n```markdown\n## {date} - {platform} (FAILED -> COPY)\n\n- **Content:** {title or first line}\n- **Source file:** {path to content file}\n- **Format:** {format}\n- **Mode:** POST (failed)\n- **Failure reason:** {Chrome not detected | login wall | element not found | rate limited | content mismatch}\n- **Fallback:** COPY mode delivered\n- **Link:** pending\n\n---\n```\n\nIf `published-log.md` doesn't exist, create it with a header:\n\n```markdown\n# Published Content Log\n\nTrack what was published, where, and when. Used by \u002Fforbotsake-retro for measurement.\n\n---\n\n{first entry}\n```\n\nAfter logging, update the source content file's frontmatter status based on the outcome:\n- **POST mode success**: set `status: published`\n- **POST mode partial**: set `status: partial`\n- **COPY mode**: do NOT change the status (content is formatted but not yet posted)\n- **FAILED → COPY fallback**: do NOT change the status (posting failed, content not live)\n\n## Phase 6: Next Steps\n\n**Orchestrated mode (`ORCHESTRATED` is `1`):** Skip this phase entirely. Confirm: \"Formatted and logged {N} pieces to published-log.md.\" Then stop.\n\n**Interactive mode (`ORCHESTRATED` is `0`):** Tell the user:\n\n> \"Logged to published-log.md. {If POST mode: 'Posted to {platform} as {handle}.'}\n>\n> {If links are pending: 'Update the link in published-log.md after posting.'}\n>\n> Track results and run `\u002Fforbotsake-retro` next week to measure what worked.\n>\n> Want to publish to another platform? Or run `\u002Fforbotsake-create` for the next piece?\"\n\nFor batch publishing, show a summary:\n> \"Published {N}\u002F{total} pieces:\n> - {piece 1}: {platform} ({mode}) {URL or 'pending'}\n> - {piece 2}: {platform} ({mode}) {URL or 'pending'}\n> ...\n>\n> Run `\u002Fforbotsake-retro` next week to measure results.\"\n","# \u002Fforbotsake-publish\n\nFrom draft to published. Format, post, log.\n\n## Preamble\n\n```bash\nFORBOTSAKE_HOME=\"${FORBOTSAKE_HOME:-$HOME\u002F.forbotsake}\"\nmkdir -p \"$FORBOTSAKE_HOME\"\n\n# Discover forbotsake install directory\n_FBS_ROOT=\"\"\nfor _FBS_CANDIDATE in \"$HOME\u002F.codex\u002Fskills\u002Fforbotsake\" \"$HOME\u002F.agents\u002Fskills\u002Fforbotsake\"; do\n  [ -d \"$_FBS_CANDIDATE\" ] && _FBS_ROOT=\"$_FBS_CANDIDATE\" && break\ndone\nif [ -z \"$_FBS_ROOT\" ]; then\n  echo \"WARNING: forbotsake not found. Install: bash \u003C(curl -fsSL https:\u002F\u002Fraw.githubusercontent.com\u002Fforbotsake\u002Fforbotsake\u002Fmain\u002Fbin\u002Finstall.sh)\"\nfi\n\n# Check for updates\n_UPD=\"\"\n[ -n \"$_FBS_ROOT\" ] && [ -x \"$_FBS_ROOT\u002Fbin\u002Fforbotsake-update-check\" ] && _UPD=$(\"$_FBS_ROOT\u002Fbin\u002Fforbotsake-update-check\" 2>\u002Fdev\u002Fnull || true)\n[ -n \"$_UPD\" ] && echo \"$_UPD\" || true\n_BRANCH=$(git branch --show-current 2>\u002Fdev\u002Fnull || echo \"unknown\")\necho \"BRANCH: $_BRANCH\"\n```\n\n```bash\n\n# Orchestrated mode (invoked by forbotsake-go, propagated via file flag)\n_ORCH_FILE=\"${FORBOTSAKE_HOME:-$HOME\u002F.forbotsake}\u002Forchestrated-$(basename \"$(git rev-parse --show-toplevel 2>\u002Fdev\u002Fnull || pwd)\")\"\nFORBOTSAKE_ORCHESTRATED=$(cat \"$_ORCH_FILE\" 2>\u002Fdev\u002Fnull || echo 0)\necho \"ORCHESTRATED: $FORBOTSAKE_ORCHESTRATED\"\n\n# Check for strategy.md\nif [ -f strategy.md ]; then\n  echo \"STRATEGY: yes\"\nelse\n  echo \"STRATEGY: no\"\n  echo \"WARNING: No strategy.md found. Run \u002Fforbotsake-marketing-start first.\"\nfi\n\n# Check for content directory\nif [ -d content\u002F ]; then\n  echo \"CONTENT_DIR: yes\"\n  ls -1 content\u002F 2>\u002Fdev\u002Fnull | head -20\nelse\n  echo \"CONTENT_DIR: no\"\nfi\n\n# Check for published log\nif [ -f published-log.md ]; then\n  echo \"PUBLISHED_LOG: yes\"\n  tail -5 published-log.md\nelse\n  echo \"PUBLISHED_LOG: no\"\nfi\n```\n\nIf output shows `UPGRADE_AVAILABLE \u003Cold> \u003Cnew>`: read the forbotsake-upgrade SKILL.md\nat `$_FBS_ROOT\u002Fforbotsake-upgrade\u002FSKILL.md` (where `_FBS_ROOT` is the variable already\nresolved in the preamble bash above) and follow the \"Inline upgrade flow\" section **Step 1\nonly**. If Step 1 results in \"Yes\" or \"Always\" (proceed with upgrade), continue through\nSteps 2-7 of the inline flow. If Step 1 results in \"Not now\" or \"Never\" (declined),\nskip Steps 2-7 entirely and continue with this skill immediately.\n\nIf output shows `JUST_UPGRADED \u003Cold> \u003Cnew>`: tell user\n\"Running forbotsake v{new} (just updated from v{old})!\" and continue.\n\nIf `STRATEGY` is `no`: \"No strategy.md found. You need positioning and channel strategy before publishing. Run `\u002Fforbotsake-marketing-start` first.\"\nStop here unless user insists.\n\nIf `CONTENT_DIR` is `no`: \"No content\u002F directory found. Run `\u002Fforbotsake-create` to write your first piece, or point me to the content you want to publish.\"\nAsk the user directly in conversation to let the user provide content manually if they prefer.\n\n## Chrome Detection\n\nAfter the preamble checks, detect whether Claude for Chrome browser tools are available. Try calling `mcp__claude-in-chrome__tabs_context_mcp` to check if the Chrome extension is connected. If it responds successfully, set CHROME_AVAILABLE to yes. If it errors or is not available, set CHROME_AVAILABLE to no.\n\nIf CHROME_AVAILABLE is yes: the user can choose POST mode (auto-post via Chrome) or COPY mode.\n\nIf CHROME_AVAILABLE is no: silently default to COPY mode. Mention once: \"Auto-posting available with the Claude for Chrome extension. Using copy-paste mode.\"\n\n## Phase 1: Select Content and Platform\n\n**Orchestrated mode (`ORCHESTRATED` is `1`):**\n- Auto-select content files: format ALL content files with `status: reviewed`, `status: revised`, or `status: reviewed-override` in frontmatter\n- Auto-select platform from each file's `channel:` frontmatter field\n- If a file has no channel specified, use the highest-scored channel from strategy.md\n- Skip the content\u002Fplatform selection direct conversation with the user\n- In Phase 4: skip \"Want me to format this for another platform too?\" — just format and log\n- After logging to published-log.md, update each published content file's frontmatter from `status: reviewed` (or `revised`\u002F`reviewed-override`) to `status: published`. This prevents re-publish loops when forbotsake-go runs again.\n- Skip Phase 5 (Next Steps) — the orchestrator handles what's next\n\n**Interactive mode (`ORCHESTRATED` is `0`):**\n\nRead `strategy.md` to understand the channel strategy and ICP.\n\nRead all files in `content\u002F` to see what's available. Check each file's frontmatter for `status` field. Files with `status: published` in the log should be noted as already published.\n\nAsk the user directly in conversation:\n\n> \"Here's what I found in your content\u002F directory:\n>\n> {list each file with a one-line summary and status}\n>\n> Which piece do you want to publish? And which platform?\n>\n> **Auto-post** (I post for you via Chrome):\n> - **X\u002FTwitter** (threads + single tweets)\n> - **LinkedIn** (posts)\n>\n> **Copy-paste + open browser** (I format it, open the compose page, you paste):\n> - **Blog** (Ghost, WordPress, Dev.to, Medium, Substack)\n> - **Reddit**\n> - **Hacker News**\n> - **Product Hunt**\n>\n> **Copy-paste only:**\n> - **Email** (formatted for your ESP)\n>\n> **CLI:**\n> - **GitHub** (PRs via `gh` CLI)\n>\n> Pick a content piece and a platform.\"\n\nIf CHROME_AVAILABLE is no, present all platforms as \"Copy-paste\" mode only. Do not show the Auto-post tier.\n\nIf the user says \"all\" or \"publish everything\", loop through each unpublished content file and process them sequentially. Between posts to the same platform, wait 30-60 seconds. Maximum 5 posts to the same platform per session to avoid triggering anti-automation measures.\n\n### Mode Selection\n\nIf CHROME_AVAILABLE is yes AND the selected platform is X\u002FTwitter or LinkedIn, ask the user directly in conversation:\n\n> \"How do you want to publish to {platform}?\n> A) **POST** — I'll post it for you right now via Chrome\n> B) **COPY** — just give me the formatted text\"\n\nFor blog platforms, Reddit, HN, and Product Hunt: if Chrome is available, offer to open the platform's compose page in a new Chrome tab after formatting. This is a \"COPY + deep link\" flow — you format the content, open the compose URL, and the user pastes it in.\n\nFor Email and GitHub: always COPY mode (email ESPs vary too much for automation; GitHub uses `gh` CLI).\n\n## Phase 1.5: Visual Asset Detection\n\nFor each selected content file, check if visual assets exist alongside it:\n\n```bash\n# For a content file like content\u002F2026-04-07-x-launch-thread.md\n# Look for: content\u002F2026-04-07-x-launch-thread-visual-*.png or *.mp4\nls content\u002F*-visual-*.{png,jpg,mp4} 2>\u002Fdev\u002Fnull\n```\n\nAlso read the content file's frontmatter for visual metadata:\n- `visual_treatment`: none\u002Ftext-card\u002Fai-image\u002Fvideo\n- `visual_status`: generated\u002Ffailed\u002Fpending\u002Fskipped\n- `visual_alt`: accessibility description\n\n**If visual assets exist** (`visual_status: generated`):\n- Note which files are available and their paths\n- These will be attached during posting (Phase 4)\n\n**If visual_treatment is not `none` but no visual file exists** (`visual_status: failed\u002Fpending\u002Fskipped`):\n- **Interactive mode:** Warn the user: \"This {channel} post has visual treatment '{visual_treatment}' but no image was generated. Options: A) Publish text-only B) Generate the image now C) Cancel\"\n- **Orchestrated mode:** Publish text-only, log the missing visual\n\n**If visual_treatment is `none`:** No visual handling needed, proceed normally.\n\n## Phase 2: Format for Platform\n\n### X\u002FTwitter Thread Format\n\nRead the knowledge framework for thread structure:\n```bash\n_SKILL_DIR=$(dirname \"$(find $HOME\u002F.codex\u002Fskills -path \"*\u002Fforbotsake-publish\u002FSKILL.md\" -type f 2>\u002Fdev\u002Fnull | head -1)\")\necho \"SKILL_DIR: $_SKILL_DIR\"\n```\n\nRead `$_SKILL_DIR\u002F..\u002Fknowledge\u002Fframeworks\u002Fcontent-strategy.md` for X thread format guidelines.\n\nFormat the content as a numbered thread following these rules:\n\n1. **Tweet 1 (The Hook):** Must stop the scroll. Lead with the most surprising, contrarian, or specific claim. No preamble. No \"I've been thinking about...\" Start with the insight. Must be under 280 characters.\n\n2. **Tweets 2-N (The Body):** One idea per tweet. Each tweet must stand alone if someone screenshots it. Use line breaks for readability. Keep each under 280 characters.\n\n3. **Final Tweet (The CTA):** What should the reader do? Follow, reply, check out the product, share? Be specific. Include the link if there is one.\n\nOutput format:\n```\n---\nTHREAD: {title}\nPlatform: X\u002FTwitter\nTweets: {count}\nCharacter counts: verified\n---\n\n1\u002F {hook tweet}\n[{character count}\u002F280]\n\n2\u002F {body tweet}\n[{character count}\u002F280]\n\n...\n\n{N}\u002F {CTA tweet}\n[{character count}\u002F280]\n```\n\nVerify every tweet is under 280 characters. If any exceeds the limit, split or rewrite it. Do NOT deliver a thread with tweets over 280 characters.\n\n### Blog Post Format\n\nFormat with full SEO structure:\n\n```\n---\nBLOG POST: {title}\nPlatform: Blog\nWord count: {count}\nReading time: {X} min\n---\n\n## SEO Meta\n- **Title tag** (under 60 chars): {title}\n- **Meta description** (under 155 chars): {description}\n- **URL slug:** {slug}\n- **Target keyword:** {keyword}\n- **Secondary keywords:** {list}\n\n## Headline Options\n1. {headline option 1 - benefit-focused}\n2. {headline option 2 - curiosity-driven}\n3. {headline option 3 - specific\u002Fnumbered}\n\n## Featured Image Suggestions\n- {description of image 1 - what to create or find}\n- {description of image 2 - alternative option}\n\n## Post Body\n\n{formatted blog post with H2\u002FH3 headers, short paragraphs, bold key phrases}\n\n## Internal Links\n- {suggest where to link to product, other content, etc.}\n```\n\n### Email Format\n\nFormat with multiple subject line options and clear structure:\n\n```\n---\nEMAIL: {title}\nPlatform: Email\nWord count: {count}\n---\n\n## Subject Line Options\n1. {subject line 1} [{character count} chars]\n2. {subject line 2} [{character count} chars]\n3. {subject line 3} [{character count} chars]\n\n## Preview Text\n{the text that shows after the subject in inbox, under 90 chars}\n\n## Email Body\n\n{formatted email - short paragraphs, conversational, one clear ask}\n\n## CTA\n- **Primary CTA:** {button text} -> {URL or action}\n- **Secondary CTA:** {text link or PS line}\n\n## Send Time Suggestion\n{best time to send based on audience from strategy.md}\n```\n\n### LinkedIn Post Format\n\nFormat for LinkedIn's algorithm and audience:\n\n```\n---\nLINKEDIN POST: {title}\nPlatform: LinkedIn\nCharacter count: {count}\u002F3000\n---\n\n{hook line - must work as the \"see more\" preview}\n\n{body - short paragraphs, line breaks between each, no walls of text}\n\n{CTA or question to drive comments}\n\n{3-5 relevant hashtags}\n```\n\n### Other Platform\n\nAsk the user directly in conversation to understand the platform's constraints (character limits, format, audience norms), then format accordingly.\n\n## Phase 3: Publish Kill Switch + Quality Check\n\n**Skip the kill switch (3a) if `FORBOTSAKE_FAST` env var is `1`.** Print: \"FORBOTSAKE_FAST=1: skipping publish kill switch.\" Jump to 3b.\n\nThis is the last gate before content goes public. Not a deep review (that happened\nin \u002Fforbotsake-content-check). This is a final sanity check: \"would I be embarrassed?\"\n\n### Phase 3a: Kill Switch (Adversarial)\n\nRead the banned patterns files:\n\n```bash\nFORBOTSAKE_HOME=\"${FORBOTSAKE_HOME:-$HOME\u002F.forbotsake}\"\n_SKILL_DIR=$(dirname \"$(find $HOME\u002F.codex\u002Fskills -path \"*\u002Fforbotsake-marketing-start\u002FSKILL.md\" -type f 2>\u002Fdev\u002Fnull | head -1)\" 2>\u002Fdev\u002Fnull)\n_FBS_ROOT=$(cd \"${_SKILL_DIR}\u002F..\" 2>\u002Fdev\u002Fnull && pwd || true)\n[ -n \"$_FBS_ROOT\" ] && [ -f \"$_FBS_ROOT\u002Fknowledge\u002Fbanned-patterns-defaults.md\" ] && echo \"DEFAULTS: found\" || echo \"DEFAULTS: not_found\"\n[ -f \"$FORBOTSAKE_HOME\u002Fbanned-patterns.md\" ] && echo \"USER_PATTERNS: found\" || echo \"USER_PATTERNS: none\"\n```\n\nRead the banned patterns file(s). Then scan the formatted content for:\n\n1. **Embarrassment test:** Read the final formatted content as if you're the ICP seeing it\n   for the first time. Would you show this to your smartest friend? Any sentence that\n   makes you cringe?\n\n2. **Factual claims:** Any claims that could be verifiably wrong? Specific numbers,\n   statistics, or comparisons that the founder hasn't verified?\n\n3. **AI tell scan:** Check for patterns from the banned patterns files. Count matches.\n   Each pattern match adds to a score. This is a contributing signal, not an automatic\n   fail. 3+ pattern matches across the piece = HOLD.\n\n4. **Platform fit:** Does the formatted version look right for the platform?\n   Character limits respected? Thread structure correct? Links formatted correctly?\n\n**Scoring:** Each dimension contributes to a GO\u002FHOLD verdict.\n- Any factual claim issue = HOLD\n- Embarrassment test fails = HOLD\n- 3+ banned pattern matches = HOLD\n- Platform fit issues = fix inline, don't HOLD\n\n**If GO:** Print \"Publish Kill Switch: GO. Content cleared for publishing.\" Continue to Phase 3b.\n\n**If HOLD:** This ALWAYS requires explicit user confirmation, even in orchestrated mode.\n\n> \"**Publish Kill Switch: HOLD**\n>\n> Last-gate check before this goes public:\n> {for each issue:}\n> - **{dimension}:** {specific concern}\n>\n> This content has not been published yet. Your call.\"\n\nAsk the user directly in conversation:\nA) Publish anyway (I've reviewed the concerns)\nB) Go back and fix it\n\nIf A: log override to metrics, continue.\nIf B: stop the publish flow. User returns to \u002Fforbotsake-content-check or manual editing.\n\nLog result:\n```bash\nFORBOTSAKE_HOME=\"${FORBOTSAKE_HOME:-$HOME\u002F.forbotsake}\"\nmkdir -p \"$FORBOTSAKE_HOME\"\necho '{\"gate\":\"publish\",\"ts\":\"'\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"'\",\"result\":\"RESULT\",\"content_file\":\"FILENAME\",\"override\":BOOL}' >> \"$FORBOTSAKE_HOME\u002Freview-metrics.jsonl\" 2>\u002Fdev\u002Fnull || true\n```\n\n### Phase 3b: Quality Check (Structural)\n\nBefore delivering the formatted content, verify:\n\n1. **Character limits:** Every tweet under 280. Blog title under 60. Email subjects tested for length.\n2. **ICP alignment:** Does this speak to the person defined in strategy.md? Would they stop scrolling?\n3. **CTA present:** Every piece has a clear next action for the reader.\n4. **No jargon leak:** The content uses the reader's language, not the builder's.\n5. **Link placeholders:** If URLs are needed, mark them clearly as `[YOUR_LINK_HERE]` so nothing is missed.\n\nIf any check fails, fix it before presenting to the user.\n\n## Phase 4: Deliver or Post\n\nThis phase splits based on the mode selected in Phase 1.\n\n### COPY Mode (all platforms)\n\nPresent the formatted content to the user with:\n\n> \"Here's your {platform}-ready content. Copy-paste ready.\n>\n> {formatted content}\n>\n> {If visual asset exists: \"**Attach this image:** `{path to visual file}`\n> Alt text: {visual_alt from frontmatter}\"}\n>\n> {If visual_treatment is video and video file exists: \"**Attach this video:** `{path to video file}`\"}\n>\n> Before you post, double-check:\n> - [ ] Links are correct\n> - [ ] Handle\u002Fusername is right\n> - [ ] {If visual: \"Image\u002Fvideo is attached\"}\n> - [ ] Timing is good (see send time suggestion if applicable)\n>\n> Want me to format this for another platform too?\"\n\nFor blog platforms, Reddit, HN, and Product Hunt: if Chrome is available, also open the platform's compose page in a new tab using `mcp__claude-in-chrome__tabs_create_mcp` so the user can paste directly. Tell the user: \"I've opened {platform} in a new tab. Paste your content there.\"\n\nSkip to Phase 5 (Log).\n\n### POST Mode (X\u002FTwitter and LinkedIn only)\n\nPOST mode automates the entire posting flow via Claude for Chrome. It works best for X and LinkedIn, which have stable compose UIs. Other platforms may have lower reliability. COPY mode always works as a fallback.\n\n#### Step 4a: Account Identity Preflight\n\nBefore posting anything, verify the logged-in account:\n\n1. Use `mcp__claude-in-chrome__tabs_create_mcp` to open the platform's home page (x.com\u002Fhome for X, linkedin.com\u002Ffeed for LinkedIn).\n2. Use `mcp__claude-in-chrome__read_page` or `mcp__claude-in-chrome__get_page_text` to find the current username\u002Fhandle on the page.\n3. Ask the user directly in conversation: \"I see you're logged in as {handle} on {platform}. Is that the right account to post from?\"\n4. If user confirms, proceed. If not, tell them to switch accounts in Chrome and try again, or use COPY mode.\n\nIf the page shows a login wall instead of the home feed, the user is not logged in. Fall back to COPY mode: \"Looks like you're not logged into {platform} in Chrome. Here's the formatted text to copy-paste instead.\"\n\n#### Step 4b: Navigate to Compose\n\nRead the publishing automation knowledge framework for platform-specific instructions:\n```bash\n_SKILL_DIR=$(dirname \"$(find $HOME\u002F.codex\u002Fskills -path \"*\u002Fforbotsake-publish\u002FSKILL.md\" -type f 2>\u002Fdev\u002Fnull | head -1)\")\necho \"SKILL_DIR: $_SKILL_DIR\"\n```\n\nRead `$_SKILL_DIR\u002F..\u002Fknowledge\u002Fframeworks\u002Fpublishing-automation.md` for the platform-specific posting flow. If this file does not exist, use the inline instructions below.\n\n**For X\u002FTwitter:**\n1. Use `mcp__claude-in-chrome__navigate` to go to `https:\u002F\u002Fx.com\u002Fcompose\u002Fpost`\n2. Wait for the compose area to load\n3. Use `mcp__claude-in-chrome__read_page` to verify the compose UI is present\n\n**For LinkedIn:**\n1. Use `mcp__claude-in-chrome__navigate` to go to `https:\u002F\u002Flinkedin.com\u002Ffeed`\n2. Use `mcp__claude-in-chrome__find` to locate the \"Start a post\" button\n3. Use `mcp__claude-in-chrome__computer` to click it\n4. Wait for the compose modal to appear\n\nIf navigation fails or the compose UI is not found:\n- **What happened:** \"Could not find the compose area on {platform}.\"\n- **Why:** \"The page may have changed, or you may not be logged in.\"\n- **Fix:** \"Try refreshing the page in Chrome, or use COPY mode instead.\"\nFall back to COPY mode and deliver the formatted text.\n\n#### Step 4c: Fill Content\n\n**X\u002FTwitter single tweet:**\n1. **If visual asset exists:** Attach image FIRST before typing text.\n   - Use `mcp__claude-in-chrome__upload_image` with the visual file path to upload the image to the compose area.\n   - If `upload_image` tool is not available: use `mcp__claude-in-chrome__computer` to click the media icon (camera\u002Fimage button), then try attaching via the file dialog. If that fails, fall back to COPY mode with the image path noted.\n   - Wait for the image preview to appear in the compose area before continuing.\n2. Use `mcp__claude-in-chrome__computer` to click the compose textarea\n3. Use `mcp__claude-in-chrome__computer` to type the tweet text\n4. Take a screenshot: `screencapture -x \u002Ftmp\u002Fforbotsake-pre-post-$(date +%s).png` and then use the Read tool to show it to the user. If screencapture fails (non-macOS), skip the screenshot and continue.\n\n**X\u002FTwitter thread:**\n1. **If visual asset exists:** Attach image to tweet 1 (hero placement) using `mcp__claude-in-chrome__upload_image` BEFORE typing text. If `visual_count` > 1, attach subsequent images to their corresponding tweets.\n2. Use `mcp__claude-in-chrome__computer` to click the compose textarea\n3. Type tweet 1 text\n3. Look for the thread \"+\" button (usually near the bottom of the compose area) and click it\n4. A new tweet textarea appears. Type tweet 2 text.\n5. Repeat for all tweets in the thread.\n6. Take a screenshot: `screencapture -x \u002Ftmp\u002Fforbotsake-pre-post-$(date +%s).png` and use the Read tool to show it.\n\n**Compose-time failure recovery:** If thread composing fails (e.g., the \"+\" button is not found after tweet N):\n1. Immediately stop.\n2. The thread has NOT been posted yet (it's still in the compose UI).\n3. Show the user: \"Could not add tweet {N+1} to the thread. Here's the full thread as copy-paste instead.\"\n4. Fall back to COPY mode. Do not log as PARTIAL (nothing was published).\n\n**Post-time failure recovery:** If the \"Post all\" button is clicked but the thread only partially appears (platform error):\n1. Use `mcp__claude-in-chrome__read_page` to check what was actually published.\n2. If partial content is live, capture the URL.\n3. Log to published-log.md as PARTIAL (see Phase 5).\n4. Show the user: \"Thread partially posted ({N}\u002F{total} tweets). Here are the remaining tweets to post manually: {remaining tweets formatted}.\"\n\n**LinkedIn post:**\n1. **If visual asset exists:** Attach image FIRST.\n   - Use `mcp__claude-in-chrome__upload_image` to upload the image into the LinkedIn compose modal.\n   - If it's a carousel (multiple text-cards), upload as a PDF document using the document attachment option.\n   - Wait for the image\u002Fdocument preview to appear.\n2. Use `mcp__claude-in-chrome__computer` to click the compose area in the modal\n3. Type the post content\n4. Take a screenshot using `screencapture` as pre-post evidence\n\n#### Step 4d: Confirm and Post\n\nBefore clicking Post, show the user a screenshot of the filled compose area and ask for confirmation:\n\n> \"Here's what's ready to post on {platform}. {screenshot}\n>\n> Ready to publish?\"\n\nAsk the user directly in conversation with options: A) Post it, B) Edit first (switch to COPY mode), C) Cancel.\n\nIf A (Post):\n1. Use `mcp__claude-in-chrome__computer` to click the Post\u002FPublish button.\n2. Wait 3 seconds for the platform to process.\n\nIf the user specifies a time (e.g., \"schedule for Monday 10am PT\"):\n1. Instead of clicking Post, look for the schedule button (calendar\u002Fclock icon near the Post button).\n2. Click it to open the scheduling UI.\n3. Set the date and time using the platform's native scheduling interface.\n4. Confirm the schedule.\n5. Log as POST in Phase 5 with a \"Scheduled for: {date\u002Ftime}\" note.\n\n#### Step 4e: Verify and Capture\n\nAfter posting:\n1. Use `mcp__claude-in-chrome__read_page` or `mcp__claude-in-chrome__get_page_text` to read the current page.\n2. Check that the URL has changed to include a post ID (e.g., `x.com\u002F{handle}\u002Fstatus\u002F{id}`).\n3. Verify that key phrases from the source content appear on the published page. Note: platforms mangle URLs (t.co links on X) and may convert special characters. Compare the main text content, not URLs or formatting.\n4. Take a screenshot: `screencapture -x \u002Ftmp\u002Fforbotsake-published-$(date +%s).png` and use the Read tool to show it.\n5. Extract the post URL.\n\nIf URL capture fails (some platforms don't redirect immediately):\nTell the user: \"Posted successfully. The URL didn't load yet. Paste it into published-log.md when you see it.\"\n\nIf content verification fails (published content doesn't match source):\nWarn: \"Published content may not match source. Please verify the post on {platform}.\"\n\nIf any step in Phase 4 fails, fall back to COPY mode and log the failure. Every error message must include:\n1. **What happened** (specific failure)\n2. **Why** (likely cause)\n3. **Fix** (actionable next step)\n\n## Phase 5: Log\n\nAppend to `published-log.md` in the project root. Create the file if it doesn't exist.\n\n### Successful POST entry:\n```markdown\n## {date} - {platform}\n\n- **Content:** {title or first line}\n- **Source file:** {path to content file}\n- **Format:** {thread\u002Fblog\u002Femail\u002Flinkedin\u002Fother}\n- **Mode:** POST\n- **Link:** {captured URL}\n- **Visual:** {visual_treatment} via {visual_provider} — {path to visual file or \"none\"}\n- **Notes:** {any relevant context}\n\n---\n```\n\n### Autonomous POST entry (cron\u002Ftick mode):\n```markdown\n## {date} - {platform} (AUTO)\n\n- **Content:** {title or first line}\n- **Source file:** {path to content file}\n- **Format:** {thread\u002Fblog\u002Femail\u002Flinkedin\u002Fother}\n- **Mode:** POST (autonomous\u002Fcron)\n- **Link:** {captured URL}\n- **Scheduled:** {ISO 8601 from content-calendar.md}\n- **Posted:** {ISO 8601 actual post time}\n- **Result:** success\n- **Notes:** Auto-posted by forbotsake-cron\n\n---\n```\n\n### Autonomous FAILED entry (cron\u002Ftick mode):\n```markdown\n## {date} - {platform} (AUTO\u002FFAILED)\n\n- **Content:** {title or first line}\n- **Source file:** {path to content file}\n- **Mode:** POST (autonomous\u002Fcron)\n- **Result:** failed\n- **Failure reason:** {specific error}\n- **Notes:** Content status set to `failed`. Set back to `reviewed` to retry.\n\n---\n```\n\n### MISSED entry (catch-up skip policy):\n```markdown\n## {date} - {platform} (MISSED)\n\n- **Content:** {title or first line}\n- **Source file:** {path to content file}\n- **Scheduled:** {ISO 8601 from content-calendar.md}\n- **Result:** missed\n- **Reason:** Laptop was asleep, catch-up policy: skip\n- **Notes:** Content remains `reviewed`. Manually post or reschedule.\n\n---\n```\n\n### Successful COPY entry:\n```markdown\n## {date} - {platform}\n\n- **Content:** {title or first line}\n- **Source file:** {path to content file}\n- **Format:** {thread\u002Fblog\u002Femail\u002Flinkedin\u002Fother}\n- **Mode:** COPY\n- **Link:** pending\n- **Visual:** {visual_treatment} via {visual_provider} — {path to visual file or \"none\"}\n- **Notes:** Copy-paste delivered. Update link after posting. {If visual exists: \"Attach image: {path}\"}\n\n---\n```\n\n### Partial publish entry (thread interrupted):\n```markdown\n## {date} - {platform} (PARTIAL)\n\n- **Content:** {title or first line}\n- **Source file:** {path to content file}\n- **Format:** thread\n- **Mode:** POST (partial)\n- **Link:** {URL of first tweet if captured}\n- **Posted:** {N}\u002F{total} tweets\n- **Notes:** Thread posting interrupted after tweet {N}. Remaining tweets delivered as copy-paste.\n\n---\n```\n\n### Failed POST entry (fell back to COPY):\n```markdown\n## {date} - {platform} (FAILED -> COPY)\n\n- **Content:** {title or first line}\n- **Source file:** {path to content file}\n- **Format:** {format}\n- **Mode:** POST (failed)\n- **Failure reason:** {Chrome not detected | login wall | element not found | rate limited | content mismatch}\n- **Fallback:** COPY mode delivered\n- **Link:** pending\n\n---\n```\n\nIf `published-log.md` doesn't exist, create it with a header:\n\n```markdown\n# Published Content Log\n\nTrack what was published, where, and when. Used by \u002Fforbotsake-retro for measurement.\n\n---\n\n{first entry}\n```\n\nAfter logging, update the source content file's frontmatter status based on the outcome:\n- **POST mode success**: set `status: published`\n- **POST mode partial**: set `status: partial`\n- **COPY mode**: do NOT change the status (content is formatted but not yet posted)\n- **FAILED → COPY fallback**: do NOT change the status (posting failed, content not live)\n\n## Phase 6: Next Steps\n\n**Orchestrated mode (`ORCHESTRATED` is `1`):** Skip this phase entirely. Confirm: \"Formatted and logged {N} pieces to published-log.md.\" Then stop.\n\n**Interactive mode (`ORCHESTRATED` is `0`):** Tell the user:\n\n> \"Logged to published-log.md. {If POST mode: 'Posted to {platform} as {handle}.'}\n>\n> {If links are pending: 'Update the link in published-log.md after posting.'}\n>\n> Track results and run `\u002Fforbotsake-retro` next week to measure what worked.\n>\n> Want to publish to another platform? Or run `\u002Fforbotsake-create` for the next piece?\"\n\nFor batch publishing, show a summary:\n> \"Published {N}\u002F{total} pieces:\n> - {piece 1}: {platform} ({mode}) {URL or 'pending'}\n> - {piece 2}: {platform} ({mode}) {URL or 'pending'}\n> ...\n>\n> Run `\u002Fforbotsake-retro` next week to measure results.\"\n",{"name":5,"description":7},"main","d91f0c567548c80403f85619693a405ed65d2b60",".agents\u002Fskills\u002Fforbotsake-publish",1,"https:\u002F\u002Fgithub.com\u002Fforbotsake\u002Fforbotsake","https:\u002F\u002Fgithub.com\u002Fforbotsake","2026-08-17 21:39:59",{"source":8,"skillName":5,"commands":64,"prompt":74,"zipAvailable":75},[65,68,71],{"tool":66,"command":67},"npx","npx skills add forbotsake\u002Fforbotsake --skill forbotsake-publish",{"tool":69,"command":70},"bunx","bunx skills add forbotsake\u002Fforbotsake --skill forbotsake-publish",{"tool":72,"command":73},"pnpm","pnpm dlx skills add forbotsake\u002Fforbotsake --skill forbotsake-publish","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fforbotsake\u002Fforbotsake\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fforbotsake-publish\u002FSKILL.md",true,[77],{"path":78,"resourceType":79,"resourceTypeDesc":80,"sizeBytes":81,"sourceHtmlUrl":82},"openai.yaml","REFERENCE","参考文档",699,"https:\u002F\u002Fgithub.com\u002Fforbotsake\u002Fforbotsake\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fforbotsake-publish\u002Fopenai.yaml",[84,106,130,157,179,195],{"skillNo":85,"name":86,"nameZh":6,"description":87,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":88,"categories":89,"keywords":90,"publishedAt":51},"01M6MWS487CZVEME2DWGT48C58","forbotsake-upgrade","Upgrade forbotsake to the latest version. Detects install type (git clone\nvs vendored), runs the upgrade, and shows what's new.\nUse when: \"upgrade forbotsake\", \"update forbotsake\", \"get latest version\",\n\"forbotsake update\".","https:\u002F\u002Fgithub.com\u002Fforbotsake\u002Fforbotsake\u002Fblob\u002Fmain\u002Fforbotsake-upgrade\u002FSKILL.md",[],[91,92,9,93,94,95,96,97,98,99,100,101,102,103,104,105],"upgrade","forbotsake upgrade","update","git","Bash","read","write","install","use","version","git clone","get","type","latest","clone",{"skillNo":107,"name":108,"nameZh":6,"description":109,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":110,"categories":111,"keywords":115,"publishedAt":51},"01M6MWRZ7XD9Q73JTRBQ0N8682","forbotsake-spy","Stage 3: RESEARCH (competitors). Analyzes 3-5 competitors to find messaging whitespace\nand positioning gaps. Produces competitor-analysis.md with a messaging matrix showing\nwhat each competitor says, what's missing, and where you can win.\nUse when: \"competitor analysis\", \"competitive research\", \"what are others doing\",\n\"market landscape\", \"who am I competing with\", \"spy on competitors\",\n\"messaging whitespace\", \"differentiation research\".\nProactively invoke when the user mentions competitors or asks how to differentiate.","https:\u002F\u002Fgithub.com\u002Fforbotsake\u002Fforbotsake\u002Fblob\u002Fmain\u002Fforbotsake-spy\u002FSKILL.md",[112],{"categoryNo":113,"categoryName":114,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000021","资料检索与研究",[116,9,117,49,118,95,119,96,97,120,99,121,122,123,124,125,126,127,128,129],"forbotsake spy","messaging","how","competitors","edit","positioning","landscape","missing","how to","differentiation","competitive","you","websearch","matrix",{"skillNo":131,"name":132,"nameZh":6,"description":133,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":134,"categories":135,"keywords":143,"publishedAt":51},"01M6MWRPHXWYB38V08BZM8SSRE","forbotsake-sharpen","Stage 4.5: SHARPEN. Takes a specific outreach target (person or organization) and\nproduces a deep execution plan with contextual research, relationship mapping,\nangle selection, and a multi-touch sequence. Reads your founder profile and strategy\nto leverage warm paths and unfair advantages.\nUse when: \"refine this plan\", \"go deeper on this\", \"sharpen execution\",\n\"how do I approach [person]\", \"outreach to [person]\", \"target [person\u002Forg]\",\n\"approach [person]\", \"engage [org]\".\nProactively invoke when the user mentions approaching a specific person or\norganization as part of their marketing strategy.\nRequires: strategy.md (from \u002Fforbotsake-marketing-start).","https:\u002F\u002Fgithub.com\u002Fforbotsake\u002Fforbotsake\u002Fblob\u002Fmain\u002Fforbotsake-sharpen\u002FSKILL.md",[136,139,140],{"categoryNo":137,"categoryName":138,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000019","营销推广",{"categoryNo":113,"categoryName":114,"taxonomyType":20,"taxonomyTypeDesc":21},{"categoryNo":141,"categoryName":142,"taxonomyType":28,"taxonomyTypeDesc":29},"01JBSEEDCAT000000000000035","市场营销",[144,145,9,146,118,95,147,96,97,120,148,149,150,151,152,153,154,155,128,156],"sharpen","forbotsake sharpen","start","plan","selection","relationship","organization","refine","deeper","deep","leverage","paths","sequence",{"skillNo":158,"name":159,"nameZh":6,"description":160,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":161,"categories":162,"keywords":165,"publishedAt":51},"01M6MWRHXHECX1N4WNHBJJQKER","forbotsake-retro","Stage 9: MEASURE. Reviews what you published, analyzes performance data,\nand produces a retro report with evidence-based recommendations.\nTells you what to double down on, what to drop, and what to try next.\nUse when: \"what worked\", \"marketing retro\", \"measure results\", \"review performance\",\n\"which content performed best\", \"should I keep doing this\".\nProactively invoke one week after \u002Fforbotsake-publish was last run.","https:\u002F\u002Fgithub.com\u002Fforbotsake\u002Fforbotsake\u002Fblob\u002Fmain\u002Fforbotsake-retro\u002FSKILL.md",[163,164],{"categoryNo":137,"categoryName":138,"taxonomyType":20,"taxonomyTypeDesc":21},{"categoryNo":141,"categoryName":142,"taxonomyType":28,"taxonomyTypeDesc":29},[166,167,9,168,169,170,32,171,95,172,96,97,120,173,174,175,127,176,177,178],"retro","forbotsake retro","review","performance","run","data","marketing","next","drop","recommendations","reviews","which","what worked",{"skillNo":180,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":181,"categories":182,"keywords":189,"publishedAt":51},"01M6MWRB8GN0AZTEVTQD1GBA8K","https:\u002F\u002Fgithub.com\u002Fforbotsake\u002Fforbotsake\u002Fblob\u002Fmain\u002Fforbotsake-publish\u002FSKILL.md",[183,184,185,188],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},{"categoryNo":186,"categoryName":187,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":26,"categoryName":27,"taxonomyType":28,"taxonomyTypeDesc":29},[32,31,9,190,191,192,42,48,193,96,97,120,194,45,44,43,39,37,36,34],"MCP","image","create","text","context",{"skillNo":196,"name":197,"nameZh":6,"description":198,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":199,"categories":200,"keywords":203,"publishedAt":51},"01M6MWR5K98QN9BDH4179Y47F0","forbotsake-marketing-start","The starting point for marketing your product. Reads your codebase to understand\nwhat you built, asks 5 hard questions about positioning, audience, and channels,\nthen produces strategy.md with your marketing strategy and first concrete move.\nUse when: \"how should I market this\", \"go-to-market\", \"GTM\", \"positioning\",\n\"I don't know how to sell this\", \"help me market\", \"marketing strategy\".\nProactively invoke when the user asks about marketing, growth, or getting users\nand no strategy.md exists yet.","https:\u002F\u002Fgithub.com\u002Fforbotsake\u002Fforbotsake\u002Fblob\u002Fmain\u002Fforbotsake-marketing-start\u002FSKILL.md",[201,202],{"categoryNo":137,"categoryName":138,"taxonomyType":20,"taxonomyTypeDesc":21},{"categoryNo":141,"categoryName":142,"taxonomyType":28,"taxonomyTypeDesc":29},[146,172,204,9,205,206,118,95,96,97,120,207,121,208,124,209,210,127,128,35],"forbotsake marketing start","go","product","me","gtm","go-to-market","move"]