Skip to content
Back to skills

Crosspost

ASecurity

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky, adapting each post per platform and never posting identical copy cross-platform. Use when the user wants one message distributed across social platforms. Do NOT use for authoring the content from scratch (content-engine) or for full launch orchestration across channels and email (marketing-campaign).

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 11, 2026
content-marketingpythonrustgobashapi

Works with

  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 11, 2026

npx -y skills add SkyyRoseLLC/DevSkyy --skill crosspost --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Crosspost?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Crosspost
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/skyyrosellc-crosspost/badge)](https://www.skillsdirectory.com/skills/skyyrosellc-crosspost)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: crosspost
description: Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky, adapting each post per platform and never posting identical copy cross-platform. Use when the user wants one message distributed across social platforms. Do NOT use for authoring the content from scratch (content-engine) or for full launch orchestration across channels and email (marketing-campaign).
origin: ECC
---

# Crosspost

Distribute content across multiple social platforms with platform-native adaptation.

## When to use

- the user wants one message posted to multiple platforms
- publishing announcements, launches, or updates across social media
- repurposing a post from one platform to others
- the user says "crosspost", "post everywhere", "share on all platforms", or "distribute this"

**When NOT to use:**

- no source post exists yet — author it with `content-engine` first; this skill distributes,
  it does not invent
- the job spans landing pages, email sequences, and ads — that is `marketing-campaign`
- the account credentials are unavailable. Publishing is an external, irreversible write:
  no credentials means stop, deliver the drafts, and name what is blocked

## Inputs

Required before any adaptation — **absent input = stop, never guess**:

1. **Source content** — the single core message, plus the primary platform (where the audience
   is biggest). Its version is drafted first and gets the best treatment.
2. **Target platform list + priority order.**
3. **Credentials / posting surface** for each target, and confirmation the account is the right
   one. For SkyyRose product claims, facts come from
   `wordpress-theme/skyyrose-flagship/data/skyyrose-catalog.csv` only.
4. **Explicit go-ahead to publish.** Posting to a live account is an external write and is
   irreversible in practice (deletes do not un-see). **STOP AND SHOW the exact per-platform text
   and wait for `y` before any publish call** — one manifest, one `y`, one send. Approval never
   carries to the next platform.

## Platform specifications

| Platform | Max length | Link handling | Hashtags | Media |
|---|---|---|---|---|
| X | 280 chars (4000 Premium) | counted in length | minimal (1–2 max) | images, video, GIFs |
| LinkedIn | 3000 chars | not counted | 3–5 relevant | images, video, docs, carousels |
| Threads | 500 chars | separate link attachment | none typical | images, video |
| Bluesky | 300 chars | via facets (rich text) | none (use feeds) | images |

## Procedure

1. Draft the primary-platform version from the source content (use `content-engine` patterns).
2. Adapt per platform — write each to its own file so the checks can run:
   - **X** — hook first, not a summary; cut to the core insight fast; links out of the main body
     when possible; thread format for longer content.
   - **LinkedIn** — strong first line (visible before "see more"); short paragraphs with line
     breaks; framed around lessons, results, professional takeaways; more explicit context than X.
   - **Threads** — conversational and casual; shorter than LinkedIn, less compressed than X;
     visual-first where possible.
   - **Bluesky** — direct and concise inside 300 chars; community-oriented; feeds/lists for
     topic targeting instead of hashtags.
3. Run the Verification checks on the draft files. Fix anything red before showing the manifest.
4. STOP AND SHOW: print each platform's exact final text and char count, then wait for `y`.
5. Publish the primary platform first. Capture the post URL for cross-referencing.
6. Publish secondaries, staggered 30–60 minutes, with cross-platform references where useful
   ("longer thread on X").
7. Verify each post landed: fetch the returned post URL and confirm it resolves.

Attribution: if crossposting someone else's content, credit the source in every version.

### Posting surfaces

Native APIs — X API v2 · LinkedIn API v2 (OAuth 2.0) · Threads API (Meta) ·
Bluesky AT Protocol. A batch service follows this shape, with per-platform bodies never equal:

```python
import os
import requests

resp = requests.post(
    "https://api.postbridge.io/v1/posts",
    headers={"Authorization": f"Bearer {os.environ['POSTBRIDGE_API_KEY']}"},
    json={
        "platforms": ["twitter", "linkedin", "threads"],
        "content": {
            "twitter": {"text": x_version},
            "linkedin": {"text": linkedin_version},
            "threads": {"text": threads_version},
        },
    },
    timeout=30,
)
resp.raise_for_status()
```

Credentials come from the environment only — never inline a token in a draft or a log line.

# Verification

Run every check **before** the STOP-AND-SHOW manifest, and the live check after publishing. A
check that errors (missing draft file → grep/awk exit 2) is a dead gate, not a pass (bug-230).

1. **Per-platform length ceiling** — over-limit copy is truncated or rejected silently:

```bash
awk 'length($0) > 280 {print "OVER-LIMIT line " NR ": " length($0) " chars"; bad=1} END {exit bad}' x.txt
```

   **PASS:** no output, exit 0. Re-run per platform with its own ceiling (X 280 · Threads 500 ·
   Bluesky 300 · LinkedIn 3000). `[repro]`

2. **No identical copy across platforms** — this skill's core rule, made falsifiable:

```bash
sort x.txt linkedin.txt threads.txt | uniq -d | grep -v '^[[:space:]]*$'
```

   **PASS:** no output (final grep exits 1). Any returned line is verbatim on two platforms —
   rewrite one before the manifest. `[repro]`

3. **The post actually landed** — a 200 from the API is not proof the post is visible:

```bash
curl -sI "https://x.com/<handle>/status/<id>" | head -1
```

   **PASS:** `HTTP/2 200`. A 404 means the publish reported success and did not stick —
   re-verify by hand rather than trusting the API response. `[live]`

Check 2 was proven able to fail before being trusted (rule 3): run it once with the same body in
two files and confirm the duplicate line is returned; then restore. **A SKIP is not a PASS** — a
platform whose length ceiling was not checked stays unchecked, and the drafter says so in the
manifest rather than letting silence read as green.

## Worked example

Real run, 2026-07-28, adapting one Black Rose drop message for X and LinkedIn. Drafts written to
the session scratchpad.

The first X draft ran 293 chars — over the ceiling, gate red:

```bash
$ awk 'length($0) > 280 {print "OVER-LIMIT line " NR ": " length($0) " chars"}' x.txt
OVER-LIMIT line 1: 293 chars
```

Trimmed to 238 chars, then both gates green:

```bash
$ wc -c < x.txt
238
$ awk 'length($0) > 280 {print "OVER-LIMIT line " NR ": " length($0) " chars"; bad=1} END {exit bad}' x.txt && echo "PASS: all lines <= 280"
PASS: all lines <= 280

$ sort x.txt linkedin.txt | uniq -d | grep -v '^[[:space:]]*$'; echo "exit=$?"
exit=1
```

All outputs observed this session `[repro]`. Zero shared lines: the X version opens
"Black Rose is armor."; the LinkedIn version reframes the same facts as a make-story with an
explicit takeaway line. Nothing was published — no credentials were manifested and no `y` was
given, so this run stops at drafts `[repro]`.

## Failure modes

| Failure | What it looks like | Rule |
|---|---|---|
| Identical copy shipped | `uniq -d` returns shared lines, or was never run | The one rule this skill exists to enforce. Run check 2 on every set |
| Published without a manifest | posts appear before the user said `y` | External irreversible write. One manifest → one `y` → one send; approval never carries to the next platform |
| Truncated CTA | link or ask cut off by the platform limit | Run check 1 per platform ceiling; links count toward X length, not LinkedIn |
| API 200 read as "posted" | success response, post not visible | bug-230 fail-open shape. Confirm with check 3 against the real URL `[live]`; a `[repro]` API response does not carry a `[live]` claim |
| Token leaked into a draft or log | credential visible in output | Environment variables only; never inline, never echo |
| Hallucinated product claim | invented price, drop date, or SKU | Catalog CSV is the only product manifest — plausible ≠ sourced (bug-096 shape) |
| Unchecked platform assumed fine | "all platforms verified" after checking one | A SKIP is not a PASS. Name the unchecked platform and who closes it |

## Related skills

`content-engine` (authoring the platform-native drafts) · `brand-voice` (the voice profile) ·
`marketing-campaign` (full multi-channel launch). Checked 2026-07-28: no `x-api` skill is
installed in `.claude/skills/` or `~/.claude/skills/` `[repro]` — X publishing means a direct
API call, not a skill handoff.

Files in this skill

  • SKILL.md8.5 KB
  • agents/openai.yaml300 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…