{"id":"68868814-32b6-4636-9545-62236f20eec7","shortId":"WBL8yR","kind":"skill","title":"postiz","tagline":">-","description":"# Postiz — Social Distribution Layer\n\nYou schedule pre-written social posts to LinkedIn, Reddit, Bluesky, Mastodon, Threads, Instagram, TikTok, YouTube, Pinterest, Discord, Slack, and any other provider a running postiz instance supports. You do NOT write copy. You do NOT tailor per platform. Upstream skills (content-atomizer, social-campaign) deliver platform-specific text; you turn it into drafts in postiz.\n\nFor Twitter/X threads, defer to `typefully` — its thread UX is canonical. You handle everything else.\n\n## North Star\n\nPostiz is a distribution execution layer in the mktg playbook:\n\n1. You never generate or rewrite copy.\n2. You never choose the platform mix — that's the user's ask or social-campaign's plan.\n3. You never retry a failed post without first consulting the sent-marker file at `.mktg/publish/{campaign}-postiz.json` — postiz has no idempotency key, and retries duplicate.\n4. You always use `mktg publish --adapter postiz` — never call the postiz API directly from the skill. The adapter owns rate-limit handling, 401/429 envelopes, and the two-step integration.id resolution.\n\n## On Activation\n\nRun these 4 steps before anything else. Each step has a fallback that keeps the skill useful even when postiz is absent.\n\n### Step 1 — Verify the catalog is registered and configured\n\n```bash\nmktg catalog info postiz --json --fields configured,missing_envs,auth.credential_envs,resolved_base\n```\n\n`catalog info <name>` returns the full `CatalogEntry` plus computed `configured`/`missing_envs`/`resolved_base` fields. The command errors with exit code 1 (NOT_FOUND) if the catalog is not in `catalogs-manifest.json` — that's the \"not registered\" signal.\n\n- Exit code 1 → postiz catalog is not registered. Tell the user: `mktg catalog add postiz --confirm`. Stop.\n- `configured: false` → env vars are missing. Build the fix string from `missing_envs` rather than hardcoding. Canonical expectation: `POSTIZ_API_KEY` (required) and `POSTIZ_API_BASE` (defaults to `https://api.postiz.com` if unset; the catalog loader returns `resolved_base: null` in that case and the skill applies the default). Stop.\n- `configured: true` → proceed to Step 2.\n\n### Step 2 — Resolve connected provider identifiers (cached)\n\n```bash\nmktg publish --adapter postiz --list-integrations --json\n```\n\nReturns `{ adapter, integrations: [{ id, identifier, name, profile, disabled, picture, customer }, ...] }` from `GET /public/v1/integrations`. Cache in `.mktg/cache/postiz-integrations.json` (TTL 15 minutes). Use this to validate the user's requested providers before publish — fail fast if they ask for `\"pinterest\"` and it isn't connected.\n\n**Critical: `identifier` is a postiz-native provider-module key, NOT a platform display name.** Single-variant providers collapse to the expected string (`\"reddit\"`, `\"bluesky\"`, `\"mastodon\"`, `\"threads\"`), but some platforms ship multiple identifiers:\n\n| Platform | Possible postiz `identifier` values |\n|---|---|\n| LinkedIn | `linkedin` (personal profile), `linkedin-page` (company page) — distinct integrations |\n| YouTube | may vary by postiz version (channel vs shorts flavors) |\n| Other | any string postiz's provider module exports |\n\nThe adapter does **exact-match** on `identifier` (no alias layer) — if the user says *\"post to LinkedIn\"* and the instance only has `linkedin-page` connected, the adapter will refuse `\"linkedin\"`. Alias handling is your job in Step 2b.\n\n### Step 2b — Handle user friendly-name aliasing (skill-layer only)\n\nWhen the agent hears *\"post to LinkedIn\"* (a platform name, not a postiz identifier), map the friendly name to the right postiz identifier(s):\n\n1. Look up the cached integrations from Step 2.\n2. Find all identifiers whose display name or known-alias matches the user's phrase. For LinkedIn, both `linkedin` and `linkedin-page` match.\n3. If exactly one matches → use it.\n4. If multiple match → present the options via AskUserQuestion. *\"You have both `linkedin` (personal) and `linkedin-page` (company) connected. Which?\"* Let the user pick; cache their choice in `.mktg/cache/postiz-aliases.json` for future sessions.\n5. If zero match → error: *\"'LinkedIn' is not connected in this postiz instance. Connected: {enumeration}. Connect it in the postiz UI first.\"*\n\n**Alias resolution lives here and NEVER in the adapter** — the adapter takes whatever you pass as `metadata.providers` and resolves against the live integrations verbatim.\n\n### Step 3 — Chain to content-atomizer FIRST if content is raw\n\nIf the user's input is a blog post, article, or long-form source (length > 500 chars or file extension `.md` in `marketing/content/`), you MUST chain `/content-atomizer` first to produce platform-native copy. Feed the atomizer's output files (`linkedin-posts.md`, `reddit-posts.md`, etc.) into this skill.\n\nIf the user's input is already platform-tailored (short-form text targeting one platform), skip atomization and proceed.\n\n### Step 4 — Tone-check against voice-profile (sanity guard only)\n\nRead `brand/voice-profile.md` if it exists. Before building the publish manifest, verify each post:\n- Does the tone spectrum match (not wildly off-brand)?\n- Is the length within the platform's character limit **and** within the voice profile's stated sentence-rhythm range?\n\nIf a check fails, surface a warning to the user and ask before proceeding. **Never rewrite.** That's content-atomizer's job — bounce back there.\n\n## How to Use\n\nThis skill runs in one of two modes. Pick by looking at the input.\n\n### Mode A — Single post to one or more platforms\n\nUser says: *\"Post this to LinkedIn and Bluesky\"* + paste text.\n\n1. Run the On Activation steps above. Step 2b resolves any user-said platform names (\"LinkedIn\") to postiz identifiers (`linkedin` or `linkedin-page` or both).\n2. Build a single-item `publish.json`. The manifest's top-level `name` is the campaign identifier (the adapter threads this into sent-marker keys — do NOT also put `campaign` in `metadata`; the adapter ignores it):\n   ```json\n   {\n     \"name\": \"ad-hoc-{timestamp}\",\n     \"items\": [{\n       \"type\": \"social\",\n       \"adapter\": \"postiz\",\n       \"content\": \"<the user's text verbatim>\",\n       \"metadata\": { \"providers\": [\"linkedin\", \"bluesky\"] }\n     }]\n   }\n   ```\n3. `mktg publish --adapter postiz --dry-run --input '<manifest>' --json` — preview.\n4. On user confirm: `mktg publish --adapter postiz --confirm --input '<manifest>' --json`.\n5. Report per-provider status from the adapter's response envelope.\n\n### Mode B — Campaign from content-atomizer output\n\nUser says: *\"Schedule my atomized blog post to LinkedIn, Reddit, and Threads\"*.\n\n1. Run On Activation.\n2. Read `marketing/social/{source-slug}/linkedin-posts.md`, `reddit-posts.md`, `threads-posts.md`. Each file contains one or more posts with YAML frontmatter matching the atomizer's contract.\n3. Build a multi-item `publish.json` with one item per (file × post). Each item's `metadata.providers` is a single-element array matching the file's platform.\n4. Same dry-run → confirm → report flow as Mode A.\n\n### Example 1 — LinkedIn-only draft\n\n```bash\nmktg publish --adapter postiz --confirm --input '{\n  \"name\": \"linkedin-announcement\",\n  \"items\": [{\n    \"type\": \"social\",\n    \"adapter\": \"postiz\",\n    \"content\": \"We shipped v2.0 today. Here is what changed...\",\n    \"metadata\": { \"providers\": [\"linkedin\"] }\n  }]\n}' --json\n```\n\n### Example 2 — Cross-platform (atomizer output + postiz distribution)\n\n```bash\n/content-atomizer marketing/content/blog/v2-announcement.md\n# Atomizer writes marketing/social/v2-announcement/{linkedin,reddit,threads}-posts.md\n\n# Build a publish.json with one item per atomized post, then:\nmktg publish --adapter postiz --dry-run --json < <tmp_publish_manifest.json>\n# Review → confirm:\nmktg publish --adapter postiz --confirm --json < <tmp_publish_manifest.json>\n```\n\n### Example 3 — Mixed batch (postiz + typefully)\n\nThis is the social-campaign Phase 5 path. You do NOT handle this standalone — the orchestrator in social-campaign routes per-post per the Phase 5 routing table.\n\n## Inputs\n\n| Input | Required | Shape | Notes |\n|---|---|---|---|\n| `content` | yes | string | Platform-tailored post text. Must fit the target platform's character limit (LinkedIn 3000, Reddit no limit, Bluesky 300, Mastodon 500, Threads 500). Failing this → Step 4 tone-check surfaces a warning. |\n| `metadata.providers` | yes | string[] | **Postiz identifiers, not platform display names.** Canonical examples: `\"linkedin\"` (personal), `\"linkedin-page\"` (company page), `\"reddit\"`, `\"bluesky\"`, `\"mastodon\"`, `\"threads\"`, `\"instagram\"`, `\"tiktok\"`, `\"youtube\"`, `\"pinterest\"`, `\"discord\"`, `\"slack\"`. Must match `identifier` exactly from `GET /public/v1/integrations`. Unknown identifiers fail fast per-item with the connected list in the error. Alias resolution (user says \"LinkedIn\" → you pick `linkedin` vs `linkedin-page`) happens in Step 2b, never in the adapter. |\n| `metadata.mediaPaths` | no | string[] | v2 stub — **ignored in v1** (draft-only, images hardcoded to `[]` in the adapter). Don't populate this field in v1 manifests; it has no effect. |\n\n**Campaign identifier does NOT live in `metadata`.** The adapter reads it from the publish manifest's top-level `name` field. If you set `metadata.campaign`, the adapter silently ignores it. Never emit `metadata.campaign`.\n\n**Validation performed at publish-time, before the network:**\n- Control chars in `content` are rejected via the base pipeline's `rejectControlChars`.\n- For each item, any identifier in `providers` that isn't in the cached `/public/v1/integrations` result produces a per-item `failed` result with `detail: \"Unconnected provider(s): X. Connected: {list}. Connect in the postiz UI first.\"`. The adapter does NOT short-circuit the whole batch — items with fully-connected providers still publish.\n- Missing `metadata.providers` fails per-item with `detail: \"Missing item.metadata.providers[] — add at least one postiz identifier\"`.\n\n## Outputs\n\nThe adapter returns the standard `AdapterResult` envelope:\n\n```json\n{\n  \"adapter\": \"postiz\",\n  \"items\": 3,\n  \"published\": 3,\n  \"failed\": 0,\n  \"errors\": [],\n  \"results\": [\n    { \"item\": 0, \"status\": \"published\", \"detail\": \"draft id=abc123 provider=linkedin\" },\n    { \"item\": 0, \"status\": \"published\", \"detail\": \"draft id=abc124 provider=reddit\" },\n    { \"item\": 0, \"status\": \"skipped\",   \"detail\": \"dedupe: sent-marker match\" }\n  ]\n}\n```\n\n**Per-provider fan-out:** one input item with N providers becomes N entries in `results[]`, each with its own status. A partial failure (Reddit rate-limited, LinkedIn succeeded) does NOT fail the whole item.\n\n**Exit-code aggregation:** the top-level `publish` command exits **0** whenever at least one item succeeds. Top-level non-zero exit only when ZERO items succeed. This matches how `typefully` and `resend` adapters already behave. Inspect `results[]` for per-item outcomes — a successful publish run can still have failed providers inside it.\n\n**Sent-marker side-effect:** successful publishes append to `.mktg/publish/<campaign>-postiz.json` with a stable hash key. Re-running the same campaign is a no-op for already-sent items.\n\n**Platform coverage table (UI hint):** after a run, render a small confirmation table showing per-provider status, draft ID, and notes.\n\n## Anti-Patterns\n\n| Anti-Pattern | Why it fails | Instead |\n|---|---|---|\n| Generate copy in this skill | Voice drift — each skill that rewrites copy diverges from `voice-profile.md`. We have one generation path (content-atomizer) for a reason: platform-specific copy rules live there. If you inline paraphrasing here, the voice profile's guardrails don't fire. | Chain `/content-atomizer` first. Feed its file output into this skill. |\n| Retry a failed post without checking the sent-marker | Postiz has no idempotency key and no webhooks. A retry without checking `.mktg/publish/<campaign>-postiz.json` duplicates the draft — if the user accepted the first one before the adapter crashed, you just ship the post twice. | Always call the adapter. The adapter consults the sent-marker *before* POSTing. Never construct your own HTTP request. |\n| Call the postiz API from within this skill | Every HTTP caller reinvents error handling. The adapter owns 401 (bad key), 429 (rate limit with Retry-After), 400 (bad provider), and network timeouts — each with structured `fix` fields. Skipping the adapter loses these. | `mktg publish --adapter postiz ...`. Always. |\n| Pass postiz `integration.id` DB primary keys in `metadata.providers` | `integration.id` values are database rows — they change between environments (hosted vs self-host vs fresh install). A hardcoded `\"42\"` breaks the moment the user rotates their instance. | Pass postiz **identifiers** (`\"linkedin\"`, `\"linkedin-page\"`, `\"bluesky\"`) verbatim — these are provider-module keys that are stable across instances. The adapter does the identifier → id lookup. |\n| Translate user-said platform names to identifiers in the adapter | Alias drift: the moment postiz ships a new provider module, any in-adapter alias layer becomes wrong. The adapter does exact-match on `identifier`; aliasing is a SKILL-layer concern. | Handle alias resolution in Step 2b of On Activation (this skill). Pass exact postiz identifiers to the adapter. |\n| Populate `metadata.campaign` in publish items | Redundant: the adapter threads `manifest.name` into sent-marker keys. If you also set `metadata.campaign`, the adapter ignores it — confusion for the agent about which wins. | Use the top-level `manifest.name` field as the campaign identifier. Don't duplicate into `metadata`. |\n| Populate `metadata.mediaPaths` in v1 | v1 is draft-only; the adapter hardcodes images to `[]`. Setting `mediaPaths` silently no-ops and wastes tokens. | Leave `mediaPaths` out of v1 manifests. Image support lands in v2 alongside `schedule` / `now` post types. |\n| Skip dry-run and go straight to `--confirm` | 30 drafts/hour is a tight rate limit; burning quota on broken manifests is wasteful. Dry-run validates providers and env vars without touching the network. | Always dry-run first. |\n| Use this skill for X threads | Typefully owns threads — better UX, per-tweet character validation, and thread-unroll view. Postiz can post to X but thread authoring is weak. | Twitter/X single post OR thread → `typefully`. Everything else → this skill. |\n\n## Progressive Enhancement\n\n| Level | State | Experience |\n|---|---|---|\n| L0 | No brand files, no postiz configured | Activation step 1 fails with `configured: false` and emits a clean fix: set `POSTIZ_API_KEY` and optionally `POSTIZ_API_BASE`. No network calls, no partial state, no crash. Exit code 3 (dependency missing). |\n| L1 | `POSTIZ_API_KEY` set, `POSTIZ_API_BASE` defaulted to `https://api.postiz.com` | The skill works for every platform the hosted instance supports. `voice-profile.md` absent → tone-check is a no-op. User feeds raw copy → warning suggests chaining content-atomizer but doesn't block. |\n| L2 | + `voice-profile.md` | Tone-check fires. Posts that violate length or tone spectrum surface warnings before the publish confirm prompt. Still functional without atomization. |\n| L3 | + `content-atomizer` has run and written `marketing/social/{slug}/` | Mode B is available. Batch-publish N atomized posts across M platforms with one confirm. |\n| L4 | + full brand + postiz configured + content-atomizer chain | End-to-end: user says \"launch my blog post on LinkedIn/Reddit/Bluesky\", orchestrator routes, atomizer writes, postiz publishes. Voice honored; sent-markers prevent dupes; partial failures roll forward. |\n\nThis skill never fails silently. At every level, the user either gets structured output (publish succeeded/failed) or a structured error with a `fix` field. Absent postiz, the skill errors cleanly — no half-finished drafts.\n\n## Related Skills\n\n- **content-atomizer** — generates platform-specific copy. MUST run before this skill for long-form source content.\n- **typefully** — X/Twitter thread handling. Complements this skill (X threads → typefully; everything else → this skill).\n- **social-campaign** — orchestrator that chains strategy/write/review/design/schedule. In Phase 5, it picks the scheduling backend per platform.\n- **brand-voice** — writes `voice-profile.md`, which this skill reads as a sanity guard in Step 4.","tags":["postiz","marketing","cli","moizibnyousaf","agent-skills","ai-agents","ai-marketing","brand-memory","brand-voice","claude-code","claude-code-skills","cmo"],"capabilities":["skill","source-moizibnyousaf","skill-postiz","topic-agent-skills","topic-ai-agents","topic-ai-marketing","topic-brand-memory","topic-brand-voice","topic-claude-code","topic-claude-code-skills","topic-cli","topic-cmo","topic-marketing-automation","topic-marketing-cli","topic-seo"],"categories":["marketing-cli"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/MoizIbnYousaf/marketing-cli/postiz","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add MoizIbnYousaf/marketing-cli","source_repo":"https://github.com/MoizIbnYousaf/marketing-cli","install_from":"skills.sh"}},"qualityScore":"0.459","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 18 github stars · SKILL.md body (16,312 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:05:51.566Z","embedding":null,"createdAt":"2026-05-04T19:06:15.305Z","updatedAt":"2026-05-18T19:05:51.566Z","lastSeenAt":"2026-05-18T19:05:51.566Z","tsv":"'/content-atomizer':694,1104,1695 '/linkedin-posts.md':1002 '/public/v1/integrations':360,1252,1383 '0':1456,1460,1470,1480,1537 '1':92,203,245,263,535,852,992,1060,2121 '15':365 '2':99,331,333,543,544,879,996,1095 '2b':498,500,860,1282,1927 '3':118,569,656,938,1020,1140,1452,1454,2150 '30':2035 '300':1203 '3000':1198 '4':145,182,576,736,949,1048,1211,2388 '400':1794 '401':1784 '401/429':169 '42':1842 '429':1787 '5':609,960,1152,1173,2365 '500':683,1205,1207 'abc123':1466 'abc124':1476 'absent':201,2175,2310 'accept':1734 'across':1869,2242 'activ':179,856,995,1930,2119 'ad':920 'ad-hoc':919 'adapt':151,163,342,349,460,487,639,641,898,914,926,941,955,968,1068,1079,1125,1135,1286,1303,1324,1342,1407,1442,1449,1562,1740,1751,1753,1782,1807,1812,1872,1888,1902,1908,1939,1947,1961,1997 'adapterresult':1446 'add':274,1434 'agent':513,1967 'aggreg':1529 'alia':468,491,554,631,1267,1889,1903,1923 'alias':506,1915 'alongsid':2021 'alreadi':720,1563,1613 'already-s':1612 'also':908,1957 'alway':147,1748,1814,2061 'announc':1075 'anti':1639,1642 'anti-pattern':1638,1641 'anyth':185 'api':157,297,302,1770,2133,2138,2155,2159 'api.postiz.com':306,2163 'append':1591 'appli':322 'array':1042 'articl':676 'ask':111,382,801 'askuserquest':584 'atom':49,661,704,732,810,978,984,1017,1099,1106,1120,1670,2193,2221,2225,2240,2255,2271,2325 'auth.credential':221 'author':2094 'avail':2235 'b':973,2233 'back':814 'backend':2370 'bad':1785,1795 'base':224,237,303,314,1366,2139,2160 'bash':211,339,1065,1103 'batch':1142,1415,2237 'batch-publish':2236 'becom':1501,1905 'behav':1564 'better':2075 'block':2197 'blog':674,985,2265 'blueski':16,416,849,937,1202,1237,1858 'bounc':813 'brand':769,2114,2250,2374 'brand-voic':2373 'brand/voice-profile.md':748 'break':1843 'broken':2045 'build':284,753,880,1021,1113 'burn':2042 'cach':338,361,539,601,1382 'call':154,1749,1767,2142 'caller':1777 'campaign':52,115,135,895,910,974,1150,1165,1316,1605,1980,2358 'canon':75,294,1227 'case':318 'catalog':206,213,225,250,265,273,310 'catalogentri':230 'catalogs-manifest.json':254 'chain':657,693,1694,2190,2256,2361 'chang':1089,1829 'channel':447 'char':684,1359 'charact':777,1195,2080 'check':739,792,1214,1709,1725,2178,2202 'choic':603 'choos':102 'circuit':1412 'clean':2129,2315 'code':244,262,1528,2149 'collaps':410 'command':240,1535 'compani':437,594,1234 'complement':2346 'comput':232 'concern':1921 'configur':210,218,233,278,326,2118,2124,2252 'confirm':276,952,957,1053,1070,1132,1137,1627,2034,2216,2247 'confus':1964 'connect':335,389,485,595,617,622,624,1262,1398,1400,1420 'construct':1762 'consult':127,1754 'contain':1007 'content':48,660,664,809,928,977,1081,1181,1361,1669,2192,2224,2254,2324,2341 'content-atom':47,659,808,976,1668,2191,2223,2253,2323 'contract':1019 'control':1358 'copi':38,98,701,1649,1659,1677,2187,2330 'coverag':1617 'crash':1741,2147 'critic':390 'cross':1097 'cross-platform':1096 'custom':357 'databas':1826 'db':1818 'dedup':1484 'default':304,324,2161 'defer':68 'deliv':53 'depend':2151 'detail':1393,1431,1463,1473,1483 'direct':158 'disabl':355 'discord':23,1244 'display':404,549,1225 'distinct':439 'distribut':4,85,1102 'diverg':1660 'doesn':2195 'draft':62,1064,1296,1464,1474,1634,1730,1994,2320 'draft-on':1295,1993 'drafts/hour':2036 'dri':944,1051,1128,2028,2050,2063 'drift':1654,1890 'dry-run':943,1050,1127,2027,2049,2062 'dupe':2281 'duplic':144,1728,1984 'effect':1315,1588 'either':2296 'element':1041 'els':79,186,2104,2353 'emit':1347,2127 'end':2258,2260 'end-to-end':2257 'enhanc':2108 'entri':1503 'enumer':623 'env':220,222,235,280,290,2055 'envelop':170,971,1447 'environ':1831 'error':241,613,1266,1457,1779,2305,2314 'etc':710 'even':197 'everi':1775,2168,2292 'everyth':78,2103,2352 'exact':463,571,1249,1911,1934 'exact-match':462,1910 'exampl':1059,1094,1139,1228 'execut':86 'exist':751 'exit':243,261,1527,1536,1550,2148 'exit-cod':1526 'expect':295,413 'experi':2111 'export':458 'extens':687 'fail':123,378,793,1208,1255,1390,1426,1455,1522,1579,1646,1706,2122,2289 'failur':1513,2283 'fallback':191 'fals':279,2125 'fan':1493 'fan-out':1492 'fast':379,1256 'feed':702,1697,2185 'field':217,238,1308,1336,1804,1977,2309 'file':132,686,707,1006,1031,1045,1699,2115 'find':545 'finish':2319 'fire':1693,2203 'first':126,630,662,695,1405,1696,1736,2065 'fit':1190 'fix':286,1803,2130,2308 'flavor':450 'flow':1055 'form':680,726,2339 'forward':2285 'found':247 'fresh':1838 'friend':504,527 'friendly-nam':503 'frontmatt':1014 'full':229,2249 'fulli':1419 'fully-connect':1418 'function':2219 'futur':607 'generat':95,1648,1666,2326 'get':359,1251,2297 'go':2031 'guard':745,2385 'guardrail':1690 'half':2318 'half-finish':2317 'handl':77,168,492,501,1157,1780,1922,2345 'happen':1279 'hardcod':293,1299,1841,1998 'hash':1598 'hear':514 'hint':1620 'hoc':921 'honor':2276 'host':1832,1836,2171 'http':1765,1776 'id':351,1465,1475,1635,1876 'idempot':140,1717 'identifi':337,352,391,424,428,466,524,533,547,871,896,1222,1248,1254,1317,1374,1439,1853,1875,1885,1914,1936,1981 'ignor':915,1292,1344,1962 'imag':1298,1999,2016 'in-adapt':1900 'info':214,226 'inlin':1683 'input':671,718,832,946,958,1071,1176,1177,1496 'insid':1581 'inspect':1565 'instagram':19,1240 'instal':1839 'instanc':32,479,621,1850,1870,2172 'instead':1647 'integr':346,350,440,540,653 'integration.id':176,1817,1823 'isn':387,1378 'item':884,923,1025,1029,1034,1076,1118,1259,1372,1389,1416,1429,1451,1459,1469,1479,1497,1525,1542,1554,1570,1615,1944 'item.metadata.providers':1433 'job':495,812 'json':216,347,917,947,959,1093,1130,1138,1448 'keep':193 'key':141,298,400,905,1599,1718,1786,1820,1865,1954,2134,2156 'known':553 'known-alia':552 'l0':2112 'l1':2153 'l2':2198 'l3':2222 'l4':2248 'land':2018 'launch':2263 'layer':5,87,469,509,1904,1920 'least':1436,1540 'leav':2010 'length':682,772,2207 'let':597 'level':891,1334,1533,1546,1975,2109,2293 'limit':167,778,1196,1201,1517,1789,2041 'linkedin':14,430,431,435,476,483,490,517,561,563,566,588,592,614,847,868,872,875,936,988,1062,1074,1092,1109,1197,1229,1232,1271,1274,1277,1468,1518,1854,1856 'linkedin-announc':1073 'linkedin-on':1061 'linkedin-pag':434,482,565,591,874,1231,1276,1855 'linkedin-posts.md':708 'linkedin/reddit/bluesky':2268 'list':345,1263,1399 'list-integr':344 'live':633,652,1320,1679 'loader':311 'long':679,2338 'long-form':678,2337 'look':536,829 'lookup':1877 'lose':1808 'm':2243 'manifest':756,887,1311,1330,2015,2046 'manifest.name':1949,1976 'map':525 'marker':131,904,1487,1585,1713,1758,1953,2279 'marketing/content':690 'marketing/content/blog/v2-announcement.md':1105 'marketing/social':998,2230 'marketing/social/v2-announcement':1108 'mastodon':17,417,1204,1238 'match':464,555,568,573,579,612,764,1015,1043,1247,1488,1557,1912 'may':442 'md':688 'mediapath':2002,2011 'metadata':912,934,1090,1322,1986 'metadata.campaign':1340,1348,1941,1959 'metadata.mediapaths':1287,1988 'metadata.providers':647,1036,1218,1425,1822 'minut':366 'miss':219,234,283,289,1424,1432,2152 'mix':105,1141 'mktg':90,149,212,272,340,939,953,1066,1123,1133,1810 'mktg/cache/postiz-aliases.json':605 'mktg/cache/postiz-integrations.json':363 'mktg/publish':134,1593,1726 'mode':826,833,972,1057,2232 'modul':399,457,1864,1898 'moment':1845,1892 'multi':1024 'multi-item':1023 'multipl':423,578 'must':692,1189,1246,2331 'n':1499,1502,2239 'name':353,405,505,520,528,550,867,892,918,1072,1226,1335,1883 'nativ':396,700 'network':1357,1798,2060,2141 'never':94,101,120,153,636,804,1283,1346,1761,2288 'new':1896 'no-op':1608,2004,2181 'non':1548 'non-zero':1547 'north':80 'note':1180,1637 'null':315 'off-brand':767 'one':572,729,823,838,1008,1028,1117,1437,1495,1541,1665,1737,2246 'op':1610,2006,2183 'option':582,2136 'orchestr':1161,2269,2359 'outcom':1571 'output':706,979,1100,1440,1700,2299 'own':164,1783,2073 'page':436,438,484,567,593,876,1233,1235,1278,1857 'paraphras':1684 'partial':1512,2144,2282 'pass':645,1815,1851,1933 'past':850 'path':1153,1667 'pattern':1640,1643 'per':43,963,1030,1119,1168,1170,1258,1388,1428,1490,1569,1631,2078,2371 'per-item':1257,1387,1427,1568 'per-post':1167 'per-provid':962,1489,1630 'per-tweet':2077 'perform':1350 'person':432,589,1230 'phase':1151,1172,2364 'phrase':559 'pick':600,827,1273,2367 'pictur':356 'pinterest':22,384,1243 'pipelin':1367 'plan':117 'platform':44,55,104,403,421,425,519,699,722,730,775,841,866,1047,1098,1185,1193,1224,1616,1675,1882,2169,2244,2328,2372 'platform-n':698 'platform-specif':54,1674,2327 'platform-tailor':721,1184 'playbook':91 'plus':231 'popul':1306,1940,1987 'possibl':426 'post':12,124,474,515,675,759,836,844,986,1011,1032,1121,1169,1187,1707,1746,1760,2024,2089,2099,2204,2241,2266 'postiz':1,2,31,64,82,137,152,156,199,215,264,275,296,301,343,395,427,445,454,523,532,620,628,870,927,942,956,1069,1080,1101,1126,1136,1143,1221,1403,1438,1450,1714,1769,1813,1816,1852,1893,1935,2087,2117,2132,2137,2154,2158,2251,2273,2311 'postiz-n':394 'postiz.json':136,1594,1727 'posts.md':1112 'pre':9 'pre-written':8 'present':580 'prevent':2280 'preview':948 'primari':1819 'proceed':328,734,803 'produc':697,1385 'profil':354,433,743,783,1688 'progress':2107 'prompt':2217 'provid':28,336,375,398,409,456,935,964,1091,1376,1395,1421,1467,1477,1491,1500,1580,1632,1796,1863,1897,2053 'provider-modul':397,1862 'publish':150,341,377,755,940,954,1067,1124,1134,1329,1353,1423,1453,1462,1472,1534,1574,1590,1811,1943,2215,2238,2274,2300 'publish-tim':1352 'publish.json':885,1026,1115 'put':909 'quota':2043 'rang':789 'rate':166,1516,1788,2040 'rate-limit':165,1515 'rather':291 'raw':666,2186 're':1601 're-run':1600 'read':747,997,1325,2381 'reason':1673 'reddit':15,415,989,1110,1199,1236,1478,1514 'reddit-posts.md':709,1003 'redund':1945 'refus':489 'regist':208,259,268 'reinvent':1778 'reject':1363 'rejectcontrolchar':1369 'relat':2321 'render':1624 'report':961,1054 'request':374,1766 'requir':299,1178 'resend':1561 'resolut':177,632,1268,1924 'resolv':223,236,313,334,649,861 'respons':970 'result':1384,1391,1458,1505,1566 'retri':121,143,1704,1723,1792 'retry-aft':1791 'return':227,312,348,1443 'review':1131 'rewrit':97,805,1658 'rhythm':788 'right':531 'roll':2284 'rotat':1848 'rout':1166,1174,2270 'row':1827 'rule':1678 'run':30,180,821,853,945,993,1052,1129,1575,1602,1623,2029,2051,2064,2227,2332 'said':865,1881 'saniti':744,2384 'say':473,843,981,1270,2262 'schedul':7,982,2022,2369 'self':1835 'self-host':1834 'sent':130,903,1486,1584,1614,1712,1757,1952,2278 'sent-mark':129,902,1485,1583,1711,1756,1951,2277 'sentenc':787 'sentence-rhythm':786 'session':608 'set':1339,1958,2001,2131,2157 'shape':1179 'ship':422,1083,1744,1894 'short':449,725,1411 'short-circuit':1410 'short-form':724 'show':1629 'side':1587 'side-effect':1586 'signal':260 'silent':1343,2003,2290 'singl':407,835,883,1040,2098 'single-el':1039 'single-item':882 'single-vari':406 'skill':46,161,195,321,508,713,820,1652,1656,1703,1774,1919,1932,2068,2106,2165,2287,2313,2322,2335,2348,2355,2380 'skill-lay':507,1918 'skill-postiz' 'skip':731,1482,1805,2026 'slack':24,1245 'slug':1001,2231 'small':1626 'social':3,11,51,114,925,1078,1149,1164,2357 'social-campaign':50,113,1148,1163,2356 'sourc':681,1000,2340 'source-moizibnyousaf' 'source-slug':999 'specif':56,1676,2329 'spectrum':763,2210 'stabl':1597,1868 'standalon':1159 'standard':1445 'star':81 'state':785,2110,2145 'status':965,1461,1471,1481,1510,1633 'step':175,183,188,202,330,332,497,499,542,655,735,857,859,1210,1281,1926,2120,2387 'still':1422,1577,2218 'stop':277,325 'straight':2032 'strategy/write/review/design/schedule':2362 'string':287,414,453,1183,1220,1289 'structur':1802,2298,2304 'stub':1291 'succeed':1519,1543,1555 'succeeded/failed':2301 'success':1573,1589 'suggest':2189 'support':33,2017,2173 'surfac':794,1215,2211 'tabl':1175,1618,1628 'tailor':42,723,1186 'take':642 'target':728,1192 'tell':269 'text':57,727,851,932,1188 'thread':18,67,72,418,899,991,1111,1206,1239,1948,2071,2074,2084,2093,2101,2344,2350 'thread-unrol':2083 'threads-posts.md':1004 'tight':2039 'tiktok':20,1241 'time':1354 'timeout':1799 'timestamp':922 'today':1085 'token':2009 'tone':738,762,1213,2177,2201,2209 'tone-check':737,1212,2176,2200 'top':890,1333,1532,1545,1974 'top-level':889,1332,1531,1544,1973 'topic-agent-skills' 'topic-ai-agents' 'topic-ai-marketing' 'topic-brand-memory' 'topic-brand-voice' 'topic-claude-code' 'topic-claude-code-skills' 'topic-cli' 'topic-cmo' 'topic-marketing-automation' 'topic-marketing-cli' 'topic-seo' 'touch':2058 'translat':1878 'true':327 'ttl':364 'turn':59 'tweet':2079 'twice':1747 'twitter/x':66,2097 'two':174,825 'two-step':173 'type':70,924,1077,1144,1559,2025,2072,2102,2342,2351 'ui':629,1404,1619 'unconnect':1394 'unknown':1253 'unrol':2085 'unset':308 'upstream':45 'use':148,196,367,574,818,1971,2066 'user':109,271,372,472,502,557,599,669,716,799,842,864,930,951,980,1269,1733,1847,1880,2184,2261,2295 'user-said':863,1879 'ux':73,2076 'v1':1294,1310,1990,1991,2014 'v2':1290,2020 'v2.0':1084 'valid':370,1349,2052,2081 'valu':429,1824 'var':281,2056 'vari':443 'variant':408 'verbatim':654,933,1859 'verifi':204,757 'version':446 'via':583,1364 'view':2086 'violat':2206 'voic':742,782,1653,1687,2275,2375 'voice-profil':741 'voice-profile.md':1662,2174,2199,2377 'vs':448,1275,1833,1837 'warn':796,1217,2188,2212 'wast':2008,2048 'weak':2096 'webhook':1721 'whatev':643 'whenev':1538 'whole':1414,1524 'whose':548 'wild':766 'win':1970 'within':773,780,1772 'without':125,1708,1724,2057,2220 'work':2166 'write':37,1107,2272,2376 'written':10,2229 'wrong':1906 'x':1397,2070,2091,2349 'x/twitter':2343 'yaml':1013 'yes':1182,1219 'youtub':21,441,1242 'zero':611,1549,1553","prices":[{"id":"2fbd8de6-569d-40d8-9dfc-eaed448870c1","listingId":"68868814-32b6-4636-9545-62236f20eec7","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"MoizIbnYousaf","category":"marketing-cli","install_from":"skills.sh"},"createdAt":"2026-05-04T19:06:15.305Z"}],"sources":[{"listingId":"68868814-32b6-4636-9545-62236f20eec7","source":"github","sourceId":"MoizIbnYousaf/marketing-cli/postiz","sourceUrl":"https://github.com/MoizIbnYousaf/marketing-cli/tree/main/skills/postiz","isPrimary":false,"firstSeenAt":"2026-05-04T19:06:15.305Z","lastSeenAt":"2026-05-18T19:05:51.566Z"}],"details":{"listingId":"68868814-32b6-4636-9545-62236f20eec7","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"MoizIbnYousaf","slug":"postiz","github":{"repo":"MoizIbnYousaf/marketing-cli","stars":18,"topics":["agent-skills","ai-agents","ai-marketing","brand-memory","brand-voice","claude-code","claude-code-skills","cli","cmo","marketing-automation","marketing-cli","seo","skills-sh","typescript"],"license":"mit","html_url":"https://github.com/MoizIbnYousaf/marketing-cli","pushed_at":"2026-05-13T21:06:05Z","description":"Agent-native marketing cli: 51 skills, 5 research agents, brand memory that compounds, plus a local Studio dashboard (beta). single agent-native cli, then /cmo in ur coding agent..","skill_md_sha":"2a52d6666686c917d58a5d12e72b799159b13d79","skill_md_path":"skills/postiz/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/MoizIbnYousaf/marketing-cli/tree/main/skills/postiz"},"layout":"multi","source":"github","category":"marketing-cli","frontmatter":{"name":"postiz","description":">-"},"skills_sh_url":"https://skills.sh/MoizIbnYousaf/marketing-cli/postiz"},"updatedAt":"2026-05-18T19:05:51.566Z"}}