{"id":"b17fa48f-2d9f-46ed-b033-172cf5c57ef8","entityType":"agent","slug":"clawhub-ratimon-openquok-core","name":"OpenQuok Core","canonicalUrl":"https://www.xpersona.co/agent/clawhub-ratimon-openquok-core","canonicalPath":"/agent/clawhub-ratimon-openquok-core","generatedAt":"2026-10-11T00:32:18.818Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T21:52:28.097Z","emptyReason":null},"description":"Schedule and manage social posts with the openquok CLI — authenticate, upload media, create drafts and scheduled posts, configure internal plugs, and read channel analytics for integrations in your OpenQuok workspace.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.2K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s173q039e4bjef64br2mkn1369897898:openquok-core","sourceUrl":"https://clawhub.ai/ratimon/openquok-core","homepage":"https://clawhub.ai/ratimon/skills/openquok-core","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/ratimon/openquok-core","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/ratimon/skills/openquok-core","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":62,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"OpenQuok Core technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T21:52:28.097Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T21:52:28.097Z","emptyReason":null},"stars":null,"forks":null,"downloads":1249,"packageName":null,"latestVersion":"1.0.9","tractionLabel":"1.2K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T21:52:28.084Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T21:52:28.097Z","lastCrawledAt":"2026-10-10T21:52:28.084Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T21:52:28.084Z","lastVerifiedAt":null,"highlights":[{"version":"1.0.9","createdAt":"2026-09-27T14:11:00.536Z","changelog":"openquok-core 1.0.9 - Added Bluesky support: new Bluesky example resources and content. - Expanded example coverage with new Bluesky follow-up, images, and text-only JSON templates. - Updated Instagram example files. - Cleaned up documentation; removed the deprecated skill-card.md file. - No core logic or workflow changes.","fileCount":66,"zipByteSize":63772},{"version":"1.0.8","createdAt":"2026-09-15T04:21:51.518Z","changelog":"openquok-core 1.0.8 - Updated documentation: SKILL.md and resources/command-reference.md were revised. - Removed legacy file: skill-card.md no longer included. - Workflow in SKILL.md expanded, now explicitly documents use of `posts:reschedule` to move publish slots and clarifies post status transitions. - No functional code or API changes; this release is documentation cleanup and clarification only.","fileCount":62,"zipByteSize":60797},{"version":"1.0.7","createdAt":"2026-09-10T05:14:32.078Z","changelog":"openquok-core 1.0.7 - Updated example files: improved and expanded docs for cross-account threads and publishing. - Clarified usage in `resources/threads-examples.md` and `resources/threads-publish.md`. - Removed obsolete `skill-card.md` file. - No changes to core logic or CLI requirements.","fileCount":62,"zipByteSize":60419},{"version":"1.0.6","createdAt":"2026-09-06T11:58:36.612Z","changelog":"openquok-core 1.0.6 - Added new social platform follow-up reply examples with images for Facebook, Threads, and X (examples/*.json). - Expanded example sets in documentation files for Facebook, Threads, and X. - Updated example usage instructions in EXAMPLES.md and provider-specific guides. - Removed redundant skill-card.md to streamline documentation.","fileCount":62,"zipByteSize":59727},{"version":"1.0.5","createdAt":"2026-09-03T12:06:35.987Z","changelog":"openquok-core 1.0.5 - Added a new Facebook Story example file (`resources/examples/facebook-story.json`). - Updated command references, provider settings, and example files for Facebook, LinkedIn, Threads, X, and YouTube to improve coverage and clarity. - Removed duplicate or outdated skill card documentation (`skill-card.md`). - Minor metadata update in SKILL.md to add Thinkrail compatibility. - Refined and expanded examples across platforms.","fileCount":58,"zipByteSize":57554},{"version":"1.0.4","createdAt":"2026-08-22T08:12:22.804Z","changelog":"openquok-core 1.0.4 - Added Dev.to example resources, including `devto-examples.md` and multiple sample JSON files for Dev.to article features. - Expanded documentation with new Dev.to usage examples and JSON templates. - Updated multiple resources (`EXAMPLES.md`, `patterns.md`, `provider-settings.md`, etc.) to include or reference Dev.to functionality. - Removed `skill-card.md` and made metadata and workspace adjustments. - No changes to CLI invocation rules or core posting workflow.","fileCount":57,"zipByteSize":54263},{"version":"1.0.3","createdAt":"2026-08-12T05:21:03.603Z","changelog":"openquok-core v1.0.3 - Updated SKILL.md with more detailed instructions for media uploads, including the use of filePath over path and stronger guidance on upload methods for large files. - Refined required fields for media JSON objects, specifying data.filePath and data.id validation. - Improved documentation for media handling and safety rules in workflows. - Removed obsolete skill-card.md file.","fileCount":52,"zipByteSize":49948},{"version":"1.0.2","createdAt":"2026-07-19T13:03:36.237Z","changelog":"openquok-core 1.0.2 changelog - Added new resource docs: \"plugs.md\" and cross-account post examples (Threads, X/Twitter). - Enhanced guides: Expanded command reference, patterns, and provider-settings documentation. - Included more integration/channel posting examples, including LinkedIn and group/channel posts. - Updated session opening/auth handling to clarify device OAuth flows on messaging hosts. - Removed legacy \"skill-card.md\" file. - Improved structure and detail in main skill documentation (SKILL.md).","fileCount":52,"zipByteSize":49858}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s173q039e4bjef64br2mkn1369897898:openquok-core","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s173q039e4bjef64br2mkn1369897898:openquok-core` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/ratimon/openquok-core before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-ratimon-openquok-core/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-ratimon-openquok-core/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-ratimon-openquok-core/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-ratimon-openquok-core/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-ratimon-openquok-core/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-ratimon-openquok-core/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T00:32:18.814Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-ratimon-openquok-core/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-ratimon-openquok-core/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-ratimon-openquok-core/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-ratimon-openquok-core/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T21:52:28.097Z","emptyReason":null},"readme":"Skill: OpenQuok Core\n\nOwner: ratimon\n\nSummary: Schedule and manage social posts with the openquok CLI — authenticate, upload media, create drafts and scheduled posts, configure internal plugs, and read channel analytics for integrations in your OpenQuok workspace.\n\nTags: latest:1.0.9\n\nVersion history:\n\nv1.0.9 | 2026-09-27T14:11:00.536Z | auto\n\nopenquok-core 1.0.9\n\n- Added Bluesky support: new Bluesky example resources and content.\n- Expanded example coverage with new Bluesky follow-up, images, and text-only JSON templates.\n- Updated Instagram example files.\n- Cleaned up documentation; removed the deprecated skill-card.md file.\n- No core logic or workflow changes.\n\nv1.0.8 | 2026-09-15T04:21:51.518Z | auto\n\nopenquok-core 1.0.8\n\n- Updated documentation: SKILL.md and resources/command-reference.md were revised.\n- Removed legacy file: skill-card.md no longer included.\n- Workflow in SKILL.md expanded, now explicitly documents use of `posts:reschedule` to move publish slots and clarifies post status transitions.\n- No functional code or API changes; this release is documentation cleanup and clarification only.\n\nv1.0.7 | 2026-09-10T05:14:32.078Z | auto\n\nopenquok-core 1.0.7\n\n- Updated example files: improved and expanded docs for cross-account threads and publishing.\n- Clarified usage in `resources/threads-examples.md` and `resources/threads-publish.md`.\n- Removed obsolete `skill-card.md` file.\n- No changes to core logic or CLI requirements.\n\nv1.0.6 | 2026-09-06T11:58:36.612Z | auto\n\nopenquok-core 1.0.6\n\n- Added new social platform follow-up reply examples with images for Facebook, Threads, and X (examples/*.json).\n- Expanded example sets in documentation files for Facebook, Threads, and X.\n- Updated example usage instructions in EXAMPLES.md and provider-specific guides.\n- Removed redundant skill-card.md to streamline documentation.\n\nv1.0.5 | 2026-09-03T12:06:35.987Z | auto\n\nopenquok-core 1.0.5\n\n- Added a new Facebook Story example file (`resources/examples/facebook-story.json`).\n- Updated command references, provider settings, and example files for Facebook, LinkedIn, Threads, X, and YouTube to improve coverage and clarity.\n- Removed duplicate or outdated skill card documentation (`skill-card.md`).\n- Minor metadata update in SKILL.md to add Thinkrail compatibility.\n- Refined and expanded examples across platforms.\n\nv1.0.4 | 2026-08-22T08:12:22.804Z | auto\n\nopenquok-core 1.0.4\n\n- Added Dev.to example resources, including `devto-examples.md` and multiple sample JSON files for Dev.to article features.\n- Expanded documentation with new Dev.to usage examples and JSON templates.\n- Updated multiple resources (`EXAMPLES.md`, `patterns.md`, `provider-settings.md`, etc.) to include or reference Dev.to functionality.\n- Removed `skill-card.md` and made metadata and workspace adjustments.\n- No changes to CLI invocation rules or core posting workflow.\n\nv1.0.3 | 2026-08-12T05:21:03.603Z | auto\n\nopenquok-core v1.0.3\n\n- Updated SKILL.md with more detailed instructions for media uploads, including the use of filePath over path and stronger guidance on upload methods for large files.\n- Refined required fields for media JSON objects, specifying data.filePath and data.id validation.\n- Improved documentation for media handling and safety rules in workflows.\n- Removed obsolete skill-card.md file.\n\nv1.0.2 | 2026-07-19T13:03:36.237Z | auto\n\nopenquok-core 1.0.2 changelog\n\n- Added new resource docs: \"plugs.md\" and cross-account post examples (Threads, X/Twitter).\n- Enhanced guides: Expanded command reference, patterns, and provider-settings documentation.\n- Included more integration/channel posting examples, including LinkedIn and group/channel posts.\n- Updated session opening/auth handling to clarify device OAuth flows on messaging hosts.\n- Removed legacy \"skill-card.md\" file.\n- Improved structure and detail in main skill documentation (SKILL.md).\n\nv1.0.1 | 2026-06-23T09:44:44.462Z | auto\n\nopenquok-core 1.0.1\n\n- Simplified session startup: initial CLI version check no longer uses npm view; only `openquok --version` and `auth:status` are run.\n- Opening message revised: offers CLI upgrade help via npm page if version seems dated, but no longer proposes auto-upgrade.\n- Skill description and instructions are more concise and user-focused.\n- Removed skill-card.md file for a slimmer footprint.\n- Clarified that the skill does not handle CLI binary upgrades—users upgrade the CLI manually.\n\nv1.0.0 | 2026-06-23T06:13:51.163Z | auto\n\nopenquok-core 1.0.0 — initial release\n\n- Implements mandatory session-opening logic: shell checks for installed and latest CLI versions, authentication status, and workspace context before assistant’s first message.\n- Requires a single opening message starting “Hi, I am the Openquok bot.” with detailed version/auth info; skips host persona greetings.\n- Adds strict media upload rules, pre-auth for API calls, and workflow for scheduling, publishing, drafts, and analytics via the Openquok CLI.\n- Ensures safe shell usage with fixed command invocations; enforces authentication and workspace context for subsequent CLI actions.\n- Includes extensive documentation and workflow rules to guide Openquok CLI-based content publishing and integration management.\n\nArchive index:\n\nArchive v1.0.9: 66 files, 63772 bytes\n\nFiles: resources/bluesky-examples.md (3832b), resources/command-reference.md (8027b), resources/devto-examples.md (4618b), resources/examples/bluesky-follow-up.json (425b), resources/examples/bluesky-images.json (319b), resources/examples/bluesky-text-only.json (167b), resources/examples/devto-article-title-tags.json (508b), resources/examples/devto-canonical.json (505b), resources/examples/devto-organization.json (515b), resources/examples/devto-series.json (413b), resources/examples/EXAMPLES.md (6184b), resources/examples/facebook-follow-up-comment-with-image.json (519b), resources/examples/facebook-follow-up-comment.json (363b), resources/examples/facebook-link-preview.json (269b), resources/examples/facebook-multi-photo.json (308b), resources/examples/facebook-reel.json (230b), resources/examples/facebook-story.json (314b), resources/examples/facebook-text-only.json (148b), resources/examples/facebook-with-image.json (222b), resources/examples/instagram-carousel.json (424b), resources/examples/instagram-feed-post.json (329b), resources/examples/instagram-follow-up-comments.json (529b), resources/examples/instagram-reel.json (218b), resources/examples/instagram-story.json (314b), resources/examples/instagram-trial-reel.json (465b), resources/examples/linkedin-document-carousel.json (587b), resources/examples/linkedin-follow-up-comment.json (367b), resources/examples/linkedin-page-document-carousel.json (527b), resources/examples/linkedin-text-post.json (138b), resources/examples/linkedin-with-video.json (243b), resources/examples/multi-platform-campaign.json (988b), resources/examples/threads-cross-account-plug.json (612b), resources/examples/threads-engagement-plug.json (436b), resources/examples/threads-follow-up-replies.json (476b), resources/examples/threads-follow-up-reply-with-image.json (533b), resources/examples/threads-media-carousel.json (301b), resources/examples/threads-text-only.json (140b), resources/examples/threads-thread-finisher.json (474b), resources/examples/threads-with-image.json (228b), resources/examples/tiktok-photo-carousel.json (527b), resources/examples/tiktok-private-draft.json (626b), resources/examples/tiktok-upload-inbox.json (460b), resources/examples/tiktok-video-direct-post.json (485b), resources/examples/x-cross-account-repost.json (501b), resources/examples/x-follow-up-replies.json (349b), resources/examples/x-follow-up-reply-with-image.json (494b), resources/examples/youtube-flat-settings.json (426b), resources/examples/youtube-video-title-privacy.json (444b), resources/examples/youtube-with-tags.json (579b), resources/examples/youtube-with-thumbnail.json (486b), resources/facebook-examples.md (5302b), resources/instagram-business-examples.md (3381b), resources/instagram-standalone-examples.md (3323b), resources/linkedin-examples.md (3720b), resources/linkedin-page-examples.md (2091b), resources/patterns.md (3515b), resources/plugs.md (4828b), resources/provider-settings.md (11803b), resources/threads-examples.md (6961b), resources/threads-publish.md (2586b), resources/tiktok-examples.md (7439b), resources/x-examples.md (6015b), resources/youtube-examples.md (3647b), skill-card.md (2016b), SKILL.md (15664b), _meta.json (132b)\n\nFile v1.0.9:SKILL.md\n\n---\nname: openquok-core\ndescription: >-\n  Schedule and manage social posts with the openquok CLI — authenticate, upload media, create drafts and scheduled posts, configure internal plugs, and read channel analytics for integrations in your OpenQuok workspace.\nhomepage: https://www.npmjs.com/package/@openquok/auto-cli\nversion: 1.0.0\nlicense: MIT\ncompatibility: Requires the global openquok CLI on PATH (see homepage). Installing this skill does not add the binary.\nprerequisites:\n  commands: [openquok]\nmetadata: {\"openclaw\":{\"emoji\":\"📮\",\"always\":true,\"requires\":{\"bins\":[\"openquok\"]},\"homepage\":\"https://www.npmjs.com/package/@openquok/auto-cli\"},\"hermes\":{\"tags\":[\"social-media\",\"openquok\",\"scheduling\"],\"category\":\"social-media\",\"requires_toolsets\":[\"terminal\"]},\"grok-bot\":{\"tags\":[\"social-media\",\"openquok\",\"scheduling\"],\"category\":\"social-media\",\"requires_toolsets\":[\"terminal\"],\"workspace_skill_path\":\"/workspace/openquok-core/SKILL.md\"},\"thinkrail\":{\"tags\":[\"social-media\",\"openquok\",\"scheduling\"],\"category\":\"social-media\",\"requires_toolsets\":[\"terminal\"],\"skill_paths\":[\"~/.pi/agent/skills/openquok-core/SKILL.md\",\".pi/skills/openquok-core/SKILL.md\"]}}\n---\n\n<!-- SPDX-FileCopyrightText: 2026 Rati Montreewat -->\n<!-- SPDX-License-Identifier: MIT -->\n\n## Session opening (first turn after reset)\n\n**When:** first assistant reply after `/new`, `/reset`, a new channel thread, or a “new session started” notice.\n\n**On that turn only:** use the OpenQuok bot voice below instead of a generic host welcome. Do **not** reuse this block on later turns.\n\n**One message only.** Run shell (below), then send **exactly one** assistant message. Forbidden on this turn:\n\n- A persona line before tools (e.g. “Hello, … I’m Atlas … What should we focus on?”).\n- A second message with only CLI version (e.g. “The OpenQuok CLI version is 0.0.6.”).\n- Repeating the host greeting after the system “new session started” line.\n\n**Shell (before any user-visible text):**\n\n```bash\nopenquok --version\nopenquok auth:status\n```\n\nIf `auth:status` shows `\"connected\": true`, also run `openquok auth:workspace`.\n\n**Required opening sentence (verbatim start):** `Hi, I am the OpenQuok bot.`\n\n**Same message must also include:**\n\n1. Installed CLI version from `openquok --version`.\n2. If the user may be on an old build: note that skill install does not upgrade the CLI and offer to walk through upgrade using the [CLI package page](https://www.npmjs.com/package/@openquok/auto-cli) — only after they agree.\n3. Auth: if connected, say you are authenticated and name **`workspace.name`**; if not, say not authenticated and offer the **two-step device flow** (below) or a programmatic token (`opo_`). **Never** run `auth:login --json` without `--no-poll` on messaging hosts — the shell exits before credentials are stored.\n\n**Fill-in template (one paragraph — replace `…` from shell output):**\n\n> Hi, I am the OpenQuok bot. OpenQuok CLI is …. [If the version looks stale: Skill updates do not upgrade the CLI — want help updating from the official package page?] [If connected: You're authenticated; workspace is …. | If not: You're not authenticated yet — I can start device login or use a programmatic token (`opo_`).]\n\nAfter this opening message, normal persona and task help are fine. Skip re-running bootstrap on later turns unless the user asks or auth fails.\n\n| Property | Value |\n|----------|-------|\n| **name** | openquok |\n| **description** | AI-ready social scheduling via the `openquok` CLI (global binary — separate from this skill): posts, integrations, media, analytics. |\n| **allowed-tools** | Bash(openquok:*) |\n\n---\n\n## ⚠️ Hard Rules (Read First)\n\n**0 — Session opening.** Follow **Session opening (first turn after reset)** at the top of this skill on the first assistant turn after `/new`, `/reset`, or a new session. Skills do not install or upgrade the `openquok` binary.\n\n**Links:** [npm `@openquok/auto-cli`](https://www.npmjs.com/package/@openquok/auto-cli) · [monorepo](https://github.com/Ratimon/openquok-monorepo/) · [CLI package](https://github.com/Ratimon/openquok-monorepo/tree/main/agent) · [openquok.com](https://www.openquok.com/)\n\n**1 — Auth before API work.** Any command that calls the API needs valid credentials. After bootstrap, re-check only when a command fails with auth errors.\n\n**2 — Media via workspace upload.** Every `-m` / `--media` / JSON `media[]` entry must be `{id, path}` from `openquok upload` or `openquok upload-from-url`. Never pass raw local paths or bare CDN URLs.\n\n```bash\nmedia_json() { openquok upload \"$1\" | jq -c '[{id: .data.id, path: (.data.path // .data.filePath)}]'; }\nopenquok posts:create -c \"…\" -s \"2026-01-01T12:00:00Z\" -i \"<uuid>\" -m \"$(media_json ./photo.jpg)\"\n```\n\nVerify upload stdout with `jq` (require `data.id` and `data.filePath`). Pass `filePath` as `media[].path`. Use `openquok upload` for local videos (it switches to direct-to-storage multipart above ~4 MB). Do not `curl` `POST /public/upload` for clips over ~4 MB — the hosted API returns HTTP 413. Remote assets: `openquok upload-from-url \"https://…\"`.\n\n---\n\n## Authentication\n\n| Order | Path | Use |\n|-------|------|-----|\n| 1 | **Device OAuth (two steps)** | Messaging agents (Telegram/Hermes): `auth:login --json --no-poll` → user opens `verification_uri_complete` → `auth:login:poll --device-code <device_code>` → `auth:status` |\n| 2 | **Programmatic token** | Headless or when device flow fails: `export OPENQUOK_API_KEY=opo_…` or `openquok auth:login --apiKey \"opo_…\"` |\n\n**Device OAuth on messaging hosts (required two-step):**\n\n```bash\nopenquok auth:login --json --no-poll\n# send verification_uri_complete to the user; wait until they confirm they authorized\nopenquok auth:login:poll --device-code \"<device_code from stdout>\"\nopenquok auth:status\n```\n\n- Tokens: [OpenQuok dashboard](https://www.openquok.com/) → **Settings → Developers → Access** → **Generate / Rotate token** (shown once).\n- Never invent verification URLs, user codes, or `device_code` — only values from `auth:login --json --no-poll` stdout.\n- Do **not** use `auth:login --json` alone on Telegram/Hermes; the host stops the shell after the first JSON and `~/.openquok/credentials.json` is never written.\n- Disk credentials in `~/.openquok/credentials.json` take precedence over `OPENQUOK_API_KEY` until `auth:logout`.\n- Workspace context: `openquok auth:workspace` → `{ workspace: { id, name } }`.\n- Optional: `OPENQUOK_API_URL`, `OPENQUOK_AUTH_SERVER` (local dev: `http://localhost:3111`).\n\nDetails: [resources/command-reference.md](./resources/command-reference.md#authentication).\n\n---\n\n## Shell safety\n\n- Run **fixed** `openquok` invocations; do not build commands by concatenating untrusted chat text into the shell.\n- Put captions and JSON payloads in **quoted** flags, heredocs, or files — not bare `$USER_INPUT` expansions.\n- Treat integration UUIDs, post IDs, and schedule times as opaque strings; reject values with shell metacharacters before use.\n\n---\n\n## Workflow\n\n| Step | Action |\n|------|--------|\n| 1 | Session opening (Rule 0): shell version/auth check, then one OpenQuok-bot greeting |\n| 2 | `openquok integrations:groups` when the workspace uses channel groups; then `integrations:list` (optionally `--group <id>`) → `integrations:settings <uuid>` per channel |\n| 3 | `integrations:trigger <uuid> <method> -d '{}'` when `output.tools` requires it |\n| 4 | `upload` / `upload-from-url` for media; ask user for file or direct image URL if missing in chat |\n| 5 | `posts:create` / `posts:status` / `posts:reschedule`; use `posts:status` to flip draft ↔ scheduled at the same time; use `posts:reschedule` to move the publish slot; agent drafts: `-t draft` + `--note`; TikTok inbox/private drafts: `--note` with finish-in-app checklist; update with `posts:review-todo` |\n| 6 | `analytics:platform` / `analytics:post` with `-d 7` \\| `30` \\| `90` |\n| 7 | Missing release id: `posts:missing` → `posts:connect --release-id` |\n\nConnect new channels in the web app; the CLI only uses UUIDs from `integrations:list`.\n\n### Integration discovery\n\n```bash\nopenquok integrations:list\nopenquok integrations:list --group <customer-group-id>\nopenquok integrations:groups\nopenquok integrations:settings <integration-uuid>\nopenquok integrations:trigger <integration-uuid> <method-name> -d '{}'\n```\n\nUse `integrations:groups` to list channel groups (`{id, name}`), then filter channels with `integrations:list --group`. Full flag reference: [resources/command-reference.md](./resources/command-reference.md#integrations).\n\n---\n\n## Posting essentials\n\n```bash\n# Scheduled post\nopenquok posts:create -c \"Caption\" -s \"2026-01-01T12:00:00Z\" -i \"<uuid>\"\n\n# Draft + human checklist\nopenquok posts:create -c \"…\" -s \"…\" -t draft -i \"<uuid>\" --note \"Check CTA before schedule\"\n\n# Per-channel captions (multi integration)\nopenquok posts:create -s \"…\" -i \"<uuid-a>,<uuid-b>\" \\\n  --bodiesByIntegrationId '{\"<uuid-a>\":\"Short\",\"<uuid-b>\":\"Long\"}'\n\n# Provider fields (confirm keys via integrations:settings)\nopenquok posts:create -c \"…\" -s \"…\" --settings '{\"post_type\":\"post\"}' -i \"<uuid>\"\n\n# Full API body\nopenquok posts:create --json ./examples/threads-text-only.json\n```\n\n- Flag-based create **requires** `-s` (ISO-8601) unless `--json` includes `scheduledAt`.\n- `posts:status` flips draft ↔ scheduled at the stored time; `posts:reschedule` moves the publish slot (`-s`). Full flags: [resources/command-reference.md](./resources/command-reference.md#postsreschedule).\n- `--settings` merges into `providerSettingsByIntegrationId` for each `-i` UUID; per-UUID maps use `--providerSettingsByIntegrationId`. See [resources/provider-settings.md](./resources/provider-settings.md).\n- Repeated `-c` (+ optional `-m`, `-d` in **milliseconds**) can build follow-up segments — for Meta Threads/Instagram follow-ups prefer nested `threads` / `instagram` buckets in channel examples.\n\nCommand surface: [resources/command-reference.md](./resources/command-reference.md).\n\n---\n\n## Plugs (internal and global)\n\nOpenQuok automates post-publish engagement with two plug types (included on paid plans):\n\n| Type | What it does | CLI |\n| --- | --- | --- |\n| **Internal plugs** | Same-account delayed reply (Threads) or actions from other connected channels (comment, repost, reshare) | Yes — set on `posts:create` via `providerSettingsByIntegrationId` |\n| **Global plugs** | Channel rules that trigger a reply/repost when likes hit a threshold (checks every 6h, up to 3 runs) | Yes — `plugs:catalog`, `plugs:list`, `plugs:upsert`, `plugs:activate`, `plugs:delete` |\n\nSupported channels: **Threads**, **X**, **LinkedIn**, **LinkedIn Page** (not Facebook, Instagram, YouTube, or TikTok).\n\n```bash\n# Internal plug — cross-account Threads comment (see examples/)\nopenquok posts:create --json ./examples/threads-cross-account-plug.json\n\n# Internal plug — same-account Threads delayed reply\nopenquok posts:create --json ./examples/threads-engagement-plug.json\n\n# Global plug — auto-reply when likes reach threshold (channel-level rule)\nopenquok plugs:catalog\nopenquok plugs:upsert <integration-id> --func autoPlugPost \\\n  --fields '[{\"name\":\"likesAmount\",\"value\":\"100\"},{\"name\":\"post\",\"value\":\"Thanks for reading!\"}]'\n```\n\nFull catalog, provider matrix, and global-plug web setup: [resources/plugs.md](./resources/plugs.md). Setting keys: [resources/provider-settings.md](./resources/provider-settings.md#internal-plugs).\n\n---\n\n## Channels (Meta)\n\nRun `integrations:settings <uuid>` for `rules`, `maxLength`, and `tools`. Match the user’s goal to the **Agent tasks** table in each channel file; publish keys and recipes are there.\n\nProvider settings overview: [resources/provider-settings.md](./resources/provider-settings.md).\n\n| Channel | `identifier` | User intents (see file) | Examples |\n|---------|----------------|-------------------------|----------|\n| Threads | `threads` | text/media/carousel, reply chain, finisher, internal plugs, global plugs, missing post | [threads-examples.md](./resources/threads-examples.md) |\n| Facebook Page | `facebook` | text, link preview, photo, carousel, Reel, comments | [facebook-examples.md](./resources/facebook-examples.md) |\n| Instagram Login | `instagram-standalone` | feed, carousel, Reel, Story, trial reel, comments | [instagram-standalone-examples.md](./resources/instagram-standalone-examples.md) |\n| Instagram Page | `instagram-business` | same as standalone (Page-linked OAuth) | [instagram-business-examples.md](./resources/instagram-business-examples.md) |\n| YouTube | `youtube` | MP4 upload, title/privacy/tags/thumbnail, channel analytics | [youtube-examples.md](./resources/youtube-examples.md) |\n| TikTok | `tiktok` | direct publish, inbox upload (`UPLOAD`), private `SELF_ONLY` drafts, privacy, toggles, analytics | [tiktok-examples.md](./resources/tiktok-examples.md) |\n| LinkedIn | `linkedin` | personal profile posts, images, video, text comments, internal plugs | [linkedin-examples.md](./resources/linkedin-examples.md) |\n| LinkedIn Page | `linkedin-page` | Page picker, document carousel, internal + global plugs, Page + post analytics | [linkedin-page-examples.md](./resources/linkedin-page-examples.md) |\n| X | `x` | text/media, thread replies, finisher, reply settings, internal + global plugs, analytics | [x-examples.md](./resources/x-examples.md) |\n| Dev.to | `devto` | markdown article, title/tags/cover/canonical/org/series, `tags` + `organizations` tools, analytics | [devto-examples.md](./resources/devto-examples.md) |\n| Bluesky | `bluesky` | text/media (≤4 images or 1 MP4), follow-up replies (`bluesky.replies`), mentions | [bluesky-examples.md](./resources/bluesky-examples.md) |\n\nThreads publish failures: [threads-publish.md](./resources/threads-publish.md).\n\n---\n\n## More recipes\n\n[resources/patterns.md](./resources/patterns.md) — multi-attachment posts, `integrations:trigger`, JSON campaigns, internal plugs, length checks, batching, retries.\n\n[resources/plugs.md](./resources/plugs.md) — internal plugs (CLI) and global plugs (web app).\n\n---\n\n## Pitfalls\n\n| Symptom | Fix |\n|---------|-----|\n| API 401 / auth errors | Two-step device OAuth (`auth:login --json --no-poll` then `auth:login:poll`); or programmatic token (`opo_`); never fake device URLs |\n| Device login OK in browser but CLI has no credentials | Messaging host ended `auth:login --json` before polling — use `--no-poll` + `auth:login:poll`, or `auth:login --apiKey` |\n| Invalid or expired device code | Re-run `auth:login --json --no-poll`; use fresh `verification_uri_complete` (~30 min) |\n| Wrong channel | Re-fetch UUID from `integrations:list` |\n| Media rejected at publish | Rule 2: upload first; for Threads see [threads-publish.md](./resources/threads-publish.md) |\n| “Image” in chat, no file | Stop; get file path or `https://` URL for `upload-from-url` |\n| Empty upload / `Content-Length: 0` | Re-upload a non-empty asset |\n| Unknown `integrations:trigger` | Method must appear in `output.tools` |\n| `--settings` parse error | Single-quoted JSON: `'{\"post_type\":\"post\"}'` |\n| Thread timing wrong | `-d` is **milliseconds**, not minutes |\n| Unknown global plug `func` | Run `plugs:catalog` and use `methodName` (e.g. `autoPlugPost`, `autoRepostPost`) |\n| Analytics rejected | `-d` must be **7**, **30**, or **90** |\n| Env key ignored | `auth:logout` if disk credentials exist |\n| Old CLI / wrong verify host | Compare `openquok --version` with the current release on the [CLI package page](https://www.npmjs.com/package/@openquok/auto-cli); reinstall or upgrade the binary there — skill install does not update it |\n\nFile v1.0.9:_meta.json\n\n{\n  \"ownerId\": \"kn7bz73j78bvq5mfqy2c9msscs896h8e\",\n  \"slug\": \"openquok-core\",\n  \"version\": \"1.0.9\",\n  \"publishedAt\": 1790518260536\n}\n\nFile v1.0.9:resources/bluesky-examples.md\n\n# Bluesky — CLI examples\n\n```bash\nBSKY_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"bluesky\") | .id')\nopenquok integrations:settings \"$BSKY_ID\"\n```\n\nRun `integrations:settings` for `output.maxLength` (300) and `rules`. Settings mechanics: [provider-settings.md](./provider-settings.md).\n\nJSON recipes: [examples/EXAMPLES.md](./examples/EXAMPLES.md#bluesky).\n\n## Supported features\n\n| Feature | Supported | Notes |\n| --- | --- | --- |\n| Text-only post | Yes | No attachment required |\n| Images | Yes | Up to **4** per main post or follow-up — upload first (Rule 2) |\n| Video | Yes | **1** MP4 per post — never mixed with images |\n| 300-grapheme cap | Yes | Main `body`, each `bluesky.replies[].message` on schedule |\n| Scheduled follow-up replies | Yes | `bluesky.replies[]` with `delaySeconds`; optional `media` per reply |\n| Mention autocomplete | Yes | Composer `@handle`; publish uses facets |\n| Link card embed | Yes | `bluesky.linkUrl` (+ optional title/description) on text-only posts — not with media or quote |\n| Quote post | Yes | `bluesky.quoteUrl` (`bsky.app` or AT URI) — not with media or link card |\n| Thread gate | Yes | `bluesky.threadGate` — who can reply after publish |\n| Video limits | Yes | One MP4 — max **300 MB**, **10** minutes |\n| Global plugs | Yes | Auto-repost / auto-plug on like threshold — channel **Plugs** tab, not create-post payload |\n| Channel / post analytics | Yes | `analytics:platform` / `analytics:post` — likes, replies, reposts, quotes via public App View |\n| Cross-post to other channels | Yes | Separate `-i` UUIDs per channel |\n\n## Agent tasks\n\n| User wants to… | JSON example |\n| --- | --- |\n| Post text only | [bluesky-text-only.json](./examples/bluesky-text-only.json) |\n| Post with images | [bluesky-images.json](./examples/bluesky-images.json) |\n| Schedule a follow-up reply | [bluesky-follow-up.json](./examples/bluesky-follow-up.json) |\n| Check channel limits | `openquok integrations:settings \"$BSKY_ID\"` |\n\n## Provider settings (`bluesky` bucket)\n\nUse nested keys under `bluesky` in `--providerSettingsByIntegrationId` (matches composer and orchestrator).\n\n| Key | Shape | When |\n| --- | --- | --- |\n| `bluesky.threadGate` | `\"everyone\"` \\| `\"mentioned\"` \\| `\"following\"` \\| `\"followers\"` \\| `\"nobody\"` | Who can reply (default `everyone`) |\n| `bluesky.linkUrl` | HTTPS URL | Optional link card — text-only; optional `linkTitle`, `linkDescription` |\n| `bluesky.quoteUrl` | `bsky.app` or AT post URI | Quote another post — not with media or link card |\n| `bluesky.replies` | `[{ \"id\": \"…\", \"message\": \"…\", \"delaySeconds\": 60, \"media\": [...] }]` | Follow-up replies after the root post publishes |\n\nNo flat CLI aliases — compose settings and follow-ups use the `bluesky` bucket only.\n\n### Reply media (`bluesky.replies[].media`)\n\nOptional on each reply row. Same shapes as the main post. Upload first (Rule 2); the worker resolves `path` to a public URL before upload to the host.\n\n- Up to four images or one MP4 per reply — not mixed.\n- Omit `media` for text-only follow-ups.\n\n**Follow-up with image** (upload first, then nest under `bluesky.replies`):\n\n```bash\nREPLY_MEDIA=$(openquok upload ./reply.png | jq -c '[{id: .data.id, path: (.data.path // .data.filePath)}]')\n\nopenquok posts:create \\\n  -s \"2026-01-01T12:00:00Z\" \\\n  -c \"Main post text.\" \\\n  -i \"$BSKY_ID\" \\\n  --providerSettingsByIntegrationId \"$(jq -nc --arg id \"$BSKY_ID\" --argjson media \"$REPLY_MEDIA\" '\n    { ($id): { bluesky: { replies: [\n      { id: \"reply-1\", message: \"Reply with image.\", delaySeconds: 120, media: $media }\n    ] } } }\n  ')\"\n```\n\nConnect in the dashboard with service URL, handle, and app password — see [social integration docs](https://www.openquok.com/docs/social-integration/bluesky) (no `GET /public/social/bluesky` connect URL).\n\nFile v1.0.9:resources/command-reference.md\n\n# OpenQuok CLI — command reference\n\nAgent-oriented reference for `@openquok/auto-cli` (`openquok`). Hard rules, auth, and workflows live in [SKILL.md](../SKILL.md).\n\n## Environment variables\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `OPENQUOK_API_KEY` | No* | — | Bearer `opo_` programmatic access token |\n| `OPENQUOK_API_URL` | No | `https://api.openquok.com` | API base (`{OPENQUOK_API_URL}/api/v1/...`) |\n| `OPENQUOK_AUTH_SERVER` | No | `https://cli-auth.openquok.com` | OAuth2 device-flow server (`/device/*`, `/health`) |\n\n\\*Either `OPENQUOK_API_KEY` or stored credentials from `openquok auth:login` is required. **Stored credentials take priority** over the env var until `auth:logout`.\n\n## Config\n\n```bash\nopenquok config:show\n```\n\nPrints resolved `api_url`, `auth_server_url`, deployment mode (`openquok_cloud` vs `custom`), and value sources — no secrets.\n\n## Authentication\n\n```bash\n# Messaging agents (Telegram/Hermes) — two steps; do not use auth:login --json alone\nopenquok auth:login --json --no-poll\nopenquok auth:login:poll --device-code \"<device_code from stdout>\"\n\n# CI / long-running shell — single process may use auth:login --json (polls until done)\nopenquok auth:login --json\n\nopenquok auth:login --apiKey \"opo_…\"   # fallback when device flow cannot complete\nopenquok auth:status\nopenquok auth:workspace             # { workspace: { id, name } } for current credentials\nopenquok auth:logout\n```\n\n- **Preference:** device OAuth before a programmatic token when the user can open a browser link.\n- **Messaging hosts:** `--json --no-poll` then `auth:login:poll` after the user authorizes — otherwise credentials are never stored.\n- **Agents:** forward `verification_uri_complete` from stdout only — never fabricate codes or URLs.\n- **Humans with TTY:** `openquok auth:login` without `--json` is fine locally.\n- **Session start:** see Rule 0 in [SKILL.md](../SKILL.md) — run version + `auth:status` (+ `auth:workspace` when connected) via shell before the first assistant message; greet as the OpenQuok bot, not the host persona.\n- **Invalid or expired code:** Re-run `auth:login --json --no-poll` and `auth:login:poll` with a fresh `device_code` (~30 min).\n\n\n## Integrations\n\n```bash\n# List all connected social channels (integration UUIDs)\nopenquok integrations:list\n\n# List integrations belonging to a specific channel group (customer)\nopenquok integrations:list --group <customer-group-id>\n\n# List all channel groups (customers) as {id, name}\nopenquok integrations:groups\n\n# Get posting rules, character limits, and settings schema for an integration\nopenquok integrations:settings <integration-uuid>\n\n# Trigger an allow-listed provider method to fetch dynamic data\nopenquok integrations:trigger <integration-uuid> <method-name> [--data '<json>' | -d '<json>']\n```\n\n- `integrations:groups` — channel groups (`integration_customers`); pass an `id` to `integrations:list --group`.\n- `integrations:settings` — rules, `maxLength`, settings schema, allow-listed `tools` (`methodName`, `dataSchema`). Publish-time keys per channel: [provider-settings.md](./provider-settings.md).\n- `integrations:trigger` — single allow-listed method; `--data` must be a JSON object when required. Live examples: Dev.to `tags` / `organizations`; LinkedIn `company` (URL in `--data`).\n- New channels are connected in the web app (OAuth, or a dashboard API key for Dev.to); the CLI uses integration UUIDs from `integrations:list`.\n\n## Posts\n\n```bash\n# List posts (default ±30 local calendar days from today)\nopenquok posts:list\nopenquok posts:list --start \"2026-01-01T00:00:00Z\" --end \"2026-02-01T00:00:00Z\"\n\n# Create or schedule posts (-s / scheduledAt is REQUIRED unless using --json)\nopenquok posts:create -c \"…\" -s \"2026-01-01T12:00:00Z\" -i \"<uuid>\"\nopenquok posts:create -c \"…\" -s \"…\" -t draft -i \"<uuid>\"\nopenquok posts:create -c \"…\" -s \"…\" -i \"<uuid>\" -m '<[{id,path}]>'\nopenquok posts:create -c \"main\" -c \"reply\" -s \"…\" -d 5000 -i \"<uuid>\"\nopenquok posts:create --json ./post.json\n\n# Manage post rows\nopenquok posts:status <post-id> --status draft\nopenquok posts:status <post-id> -s schedule\nopenquok posts:reschedule <post-id> -s \"2026-06-15T14:30:00.000Z\"\nopenquok posts:reschedule <post-id> -s \"2026-06-20T10:00:00.000Z\" --action schedule --republish\nopenquok posts:review-todo <post-id> --note \"…\"\nopenquok posts:delete <post-id>\n\n# Resolve missing release_id before per-post analytics\nopenquok posts:missing <post-id>\nopenquok posts:connect <post-id> --release-id \"<provider-release-id>\"\n```\n\n### `posts:list`\n\n- Default window: ±30 **local calendar** days from today (ISO on the wire).\n- Override: `--start` / `--end` (aliases `--startDate` / `--endDate`).\n- Filter: `-i` / `--integrations` / `--integrationIds` (CSV), `--customer` / `--customerGroupId`.\n\n### `posts:status`\n\n- Takes a **post row** id from `posts:list` (same as `posts:delete`).\n- Flips `draft` ↔ `scheduled` at the stored publish time.\n\n### `posts:reschedule`\n\n- Takes a **post row** id from `posts:list` (any row in the group).\n- Required `-s` / `--scheduledAt` — new publish time (ISO-8601); same field as `POST /public/posts`.\n- `--action update` (default) — moves `publishDate` only; preserves each row's state (draft, scheduled, or published).\n- `--action schedule` — re-queues publishing at the new time and clears `releaseId`, `releaseUrl`, and errors.\n- `--republish` — required when `--action schedule` and the group already has published rows; otherwise the API returns `400`.\n- Use `posts:status` when you only need to flip draft ↔ scheduled at the **same** stored time — not to move the slot.\n\n### `posts:missing` / `posts:connect`\n\n- Use when `release_id` is `\"missing\"`: list provider candidates, then link with `--release-id` (aliases `--releaseId`, `-r`) for per-post analytics.\n\n### Media flags (`-m` / `--media`)\n\n- Value must be a JSON array of `{ \"id\", \"path\" }` from `openquok upload` or `openquok upload-from-url` (see Rule 2 in SKILL.md).\n- **Thread-style posts:** repeated `-c` for segments; optional repeated `-m` pairs with leading segments. `-d` is **milliseconds** between segments (default 5000).\n\n### `--json` / `-j`\n\n- Full `POST /public/posts` payload: `scheduledAt`, `status`, `bodiesByIntegrationId`, `providerSettingsByIntegrationId`, `media`, tags, etc.\n\n## Analytics\n\n```bash\n# Platform-level metrics for a connected channel (7, 30, or 90 days)\nopenquok analytics:platform <integration-uuid> [--days 7|30|90]\n\n# Per-post metrics for a published post row\nopenquok analytics:post <post-id> [--days 7|30|90]\n```\n\n- `--days` / `-d` must be **7**, **30**, or **90** (default 7).\n- `analytics:post` returns `[]` for drafts/queued rows.\n\n## Plugs\n\n| Type | CLI support | How |\n| --- | --- | --- |\n| **Internal plugs** | Yes | Per-post `providerSettingsByIntegrationId` on `posts:create` — `threads.internalEngagementPlug`, `*.crossAccountPlugs` |\n| **Global plugs** | Yes | `plugs:catalog`, `plugs:list <integration-id>`, `plugs:upsert`, `plugs:activate`, `plugs:delete` |\n\n```bash\nopenquok plugs:catalog\nopenquok plugs:list <integration-id>\nopenquok plugs:upsert <integration-id> --func autoPlugPost \\\n  --fields '[{\"name\":\"likesAmount\",\"value\":\"100\"},{\"name\":\"post\",\"value\":\"Thanks!\"}]'\nopenquok plugs:activate <plug-id> --activated true\nopenquok plugs:delete <plug-id>\n```\n\nChannels with plugs: Threads, X, LinkedIn, LinkedIn Page. Full catalog: [plugs.md](./plugs.md).\n\n## Media upload\n\n```bash\n# Upload a local file; returns media id and path for posts:create\nopenquok upload ./image.png\n\n# Upload from a remote URL; returns media id and path\nopenquok upload-from-url \"https://cdn.example.com/banner.png\"\n```\n\nBoth return `data.id` and `data.filePath` for use in `-m` / JSON `media` (`path` is the post field). `openquok upload` switches to direct-to-storage multipart for files over ~4 MB so hosted Cloud does not return HTTP 413.\n\n## Help\n\n```bash\nopenquok --help\nopenquok posts:create --help\n```\n\nFile v1.0.9:resources/devto-examples.md\n\n# Dev.to (`devto`) — CLI examples\n\n```bash\nDEVTO_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"devto\") | .id')\nopenquok integrations:settings \"$DEVTO_ID\"\n```\n\nConnect the channel in the OpenQuok dashboard with a personal API key (DEV Settings → Extensions). There is no public OAuth start URL.\n\nRun `integrations:settings` for `output.rules`, `output.maxLength`, typed `settingsSchema`, and allow-listed `output.tools` (`tags`, `organizations`).\n\nSettings mechanics: [provider-settings.md](./provider-settings.md). JSON recipes: [examples/EXAMPLES.md](./examples/EXAMPLES.md#devto).\n\n## Supported features\n\n| Feature | Supported | Notes |\n| --- | --- | --- |\n| Markdown article body | Yes | Root `-c` caption (up to 100,000 characters) |\n| Title | Yes | Required; min 2 characters (`title`) |\n| Tags | Yes | Up to 4 names; strings or `{ value, label }` |\n| Cover image | Yes | `main_image` / `mainImage` `{ path }` from a prior `upload` |\n| Canonical URL | Yes | `canonical` (aliases `canonical_url`, `canonicalUrl`) |\n| Organization | Yes | Numeric id from `integrations:trigger … organizations` |\n| Series | Yes | Free-text `series`; Dev.to creates the series if missing |\n| Tag / org lookup | Yes | `integrations:trigger` `tags` and `organizations` |\n| Channel / article analytics | Yes | `analytics:platform` and `analytics:post` — page views, reactions, comments |\n| Follow-up comments | No | Out of scope |\n| Public OAuth connect | No | Dashboard API key only |\n\n## Agent tasks\n\n| User wants to… | JSON example |\n| --- | --- |\n| Schedule a markdown article with title and tags | [devto-article-title-tags.json](./examples/devto-article-title-tags.json) |\n| Add the article to a series | [devto-series.json](./examples/devto-series.json) |\n| Syndicate with a canonical URL | [devto-canonical.json](./examples/devto-canonical.json) |\n| Publish under an organization with a cover | [devto-organization.json](./examples/devto-organization.json) |\n| List tag suggestions | `openquok integrations:trigger \"$DEVTO_ID\" tags` |\n| List organizations the key can publish under | `openquok integrations:trigger \"$DEVTO_ID\" organizations` |\n| See the typed settings schema | `openquok integrations:settings \"$DEVTO_ID\"` |\n| Track account performance | [Discover integration](#discover-integration) → `analytics:platform` |\n| Inspect a published article | [Post insights](#post-insights) |\n\n## Provider settings\n\nFlat JSON on `--settings` or inside `--providerSettingsByIntegrationId` for the Dev.to UUID. Nested `devto.*` matches the web composer bucket.\n\n| Key | Values | When |\n| --- | --- | --- |\n| `title` | string (min 2 chars) | Required for valid publish |\n| `tags` | strings or `[{ \"value\": \"…\", \"label\": \"…\" }]` | Optional; max 4 |\n| `canonical` | URL string | Optional syndication URL |\n| `canonical_url` / `canonicalUrl` | URL string | Aliases for `canonical` |\n| `organization` | integer id | Optional; from `organizations` tool |\n| `organization_id` / `organizationId` | integer | Aliases for `organization` |\n| `series` | string | Optional series name; creates the series if missing |\n| `main_image` / `mainImage` | `{ \"path\": \"…\" }` or path string | Optional cover after upload |\n| `devto.title` | string | Same as `title` (composer bucket) |\n| `devto.tags` | tag array | Same as `tags` |\n| `devto.canonical` | URL string | Same as `canonical` |\n| `devto.organization` | integer | Same as `organization` |\n| `devto.series` | string | Same as `series` |\n| `devto.mainImage` | `{ \"path\": \"…\" }` | Same as `mainImage` |\n\n**Rules:** Title min 2 characters. At most 4 tags. Body is markdown. Cover path must come from `openquok upload` / `upload-from-url` (Rule 2), not a raw local path. Duplicate canonical URLs fail at publish with a clear error.\n\n## Run an example\n\n```bash\nopenquok posts:create --json ./examples/devto-article-title-tags.json\nopenquok posts:create --json ./examples/devto-series.json\n```\n\n## Discover integration\n\n```bash\nopenquok integrations:settings \"$DEVTO_ID\"\nopenquok integrations:trigger \"$DEVTO_ID\" tags\nopenquok integrations:trigger \"$DEVTO_ID\" organizations\nopenquok analytics:platform \"$DEVTO_ID\" -d 30\n```\n\nPlatform analytics return daily page views, reactions, and comments for the connected Dev.to account (`-d 7` \\| `30` \\| `90`).\n\n## Post insights\n\n```bash\nPOST_ID=$(openquok posts:list | jq -r '.items[] | select(.identifier==\"devto\") | .id' | head -1)\nopenquok analytics:post \"$POST_ID\" -d 7\n```\n\nPer-post analytics use the same metric labels for a **published** article (linked Forem article id). Drafts and queued rows return `[]`.\n\nFile v1.0.9:resources/examples/EXAMPLES.md\n\n# OpenQuok CLI — JSON post examples\n\nCopy-paste payloads for `openquok posts:create --json ./examples/<file>.json`. Each file uses the **POST /public/posts** shape (`scheduledAt`, `status`, `body`, `integrationIds`, optional `media`, `providerSettingsByIntegrationId`, …).\n\n## Before you post\n\n1. Replace `<integration-id>` with a UUID from `openquok integrations:list`.\n2. Replace `<media-id>`, `<reply-media-id>`, and `https://cdn.example.com/…` paths with `{id, path}` from `openquok upload` or `openquok upload-from-url` (Rule 2 in [SKILL.md](../../SKILL.md)). Follow-up reply images use the same `media` shape on `replies[]` rows — upload each file before `posts:create`.\n3. Run `openquok integrations:settings <integration-id>` for `maxLength`, `rules`, and allow-listed `integrations:trigger` methods.\n\nGlobal plugs (likes-threshold channel rules) are configured with `plugs:*` commands — see [plugs.md](../plugs.md).\n\n```bash\nopenquok posts:create --json ./examples/threads-text-only.json\n```\n\n## Threads\n\n| File | Scenario |\n| --- | --- |\n| [threads-text-only.json](./threads-text-only.json) | Text-only scheduled post |\n| [threads-with-image.json](./threads-with-image.json) | Single image |\n| [threads-media-carousel.json](./threads-media-carousel.json) | Multi-image carousel |\n| [threads-follow-up-replies.json](./threads-follow-up-replies.json) | `threads.replies` chain (text only) |\n| [threads-follow-up-reply-with-image.json](./threads-follow-up-reply-with-image.json) | `threads.replies` with image on a reply row |\n| [threads-thread-finisher.json](./threads-thread-finisher.json) | Finisher + follow-ups |\n| [threads-engagement-plug.json](./threads-engagement-plug.json) | Internal plug — `threads.internalEngagementPlug` (same-account delayed reply) |\n| [threads-cross-account-plug.json](./threads-cross-account-plug.json) | Internal plug — `threads.crossAccountPlugs` (comment from other Threads channels) |\n\n## Facebook Page\n\n| File | Scenario |\n| --- | --- |\n| [facebook-text-only.json](./facebook-text-only.json) | Text feed post |\n| [facebook-with-image.json](./facebook-with-image.json) | Single photo |\n| [facebook-link-preview.json](./facebook-link-preview.json) | Link preview (`url`) |\n| [facebook-reel.json](./facebook-reel.json) | Reel from MP4 |\n| [facebook-story.json](./facebook-story.json) | Story (`post_type: story`) |\n| [facebook-multi-photo.json](./facebook-multi-photo.json) | Multi-photo carousel |\n| [facebook-follow-up-comment.json](./facebook-follow-up-comment.json) | Follow-up comments via `replies` (text only) |\n| [facebook-follow-up-comment-with-image.json](./facebook-follow-up-comment-with-image.json) | Follow-up comment with one image on `facebook.replies[]` |\n\n## Instagram\n\nShared recipes — use the same JSON with `instagram-standalone` or `instagram-business` integration UUIDs.\n\n| File | Scenario |\n| --- | --- |\n| [instagram-feed-post.json](./instagram-feed-post.json) | Feed image |\n| [instagram-carousel.json](./instagram-carousel.json) | Multi-image carousel |\n| [instagram-reel.json](./instagram-reel.json) | Reel (MP4) |\n| [instagram-story.json](./instagram-story.json) | Story |\n| [instagram-trial-reel.json](./instagram-trial-reel.json) | Trial Reel + collaborators |\n| [instagram-follow-up-comments.json](./instagram-follow-up-comments.json) | Text follow-ups via `instagram.replies` |\n\n## YouTube\n\n| File | Scenario |\n| --- | --- |\n| [youtube-video-title-privacy.json](./youtube-video-title-privacy.json) | Video + title + privacy |\n| [youtube-with-tags.json](./youtube-with-tags.json) | Nested `youtube.*` + tags |\n| [youtube-with-thumbnail.json](./youtube-with-thumbnail.json) | Custom thumbnail |\n| [youtube-flat-settings.json](./youtube-flat-settings.json) | Flat `--settings`-style keys |\n\n## TikTok\n\n| File | Scenario |\n| --- | --- |\n| [tiktok-video-direct-post.json](./tiktok-video-direct-post.json) | Direct publish + privacy |\n| [tiktok-photo-carousel.json](./tiktok-photo-carousel.json) | Photo carousel + title |\n| [tiktok-upload-inbox.json](./tiktok-upload-inbox.json) | Creator inbox (`UPLOAD`) |\n| [tiktok-private-draft.json](./tiktok-private-draft.json) | Private draft (`SELF_ONLY`) |\n\n## LinkedIn\n\n| File | Scenario |\n| --- | --- |\n| [linkedin-text-post.json](./linkedin-text-post.json) | Personal profile text |\n| [linkedin-document-carousel.json](./linkedin-document-carousel.json) | Image → PDF document carousel (`post_as_images_carousel`, `carousel_name`) |\n| [linkedin-with-video.json](./linkedin-with-video.json) | Single MP4 video |\n| [linkedin-follow-up-comment.json](./linkedin-follow-up-comment.json) | Text follow-up comments |\n| [linkedin-page-document-carousel.json](./linkedin-page-document-carousel.json) | Page document carousel (`linkedin.postAsImagesCarousel`) |\n\n## X\n\n| File | Scenario |\n| --- | --- |\n| [x-follow-up-replies.json](./x-follow-up-replies.json) | Quote-less reply chain via `x.replies` (text only) |\n| [x-follow-up-reply-with-image.json](./x-follow-up-reply-with-image.json) | Follow-up reply with image on `x.replies[]` |\n| [x-cross-account-repost.json](./x-cross-account-repost.json) | Internal plug — `x.crossAccountPlugs` (repost from other X channels) |\n\n## Dev.to\n\n| File | Scenario |\n| --- | --- |\n| [devto-article-title-tags.json](./devto-article-title-tags.json) | Markdown article + title + tags |\n| [devto-series.json](./devto-series.json) | Free-text series name |\n| [devto-canonical.json](./devto-canonical.json) | Canonical URL syndication |\n| [devto-organization.json](./devto-organization.json) | Organization id + cover `mainImage.path` |\n\n## Bluesky\n\n| File | Scenario |\n| --- | --- |\n| [bluesky-text-only.json](./bluesky-text-only.json) | Text-only scheduled post |\n| [bluesky-images.json](./bluesky-images.json) | Multi-image post |\n| [bluesky-follow-up.json](./bluesky-follow-up.json) | `bluesky.replies` follow-up |\n\n## Multi-channel\n\n| File | Scenario |\n| --- | --- |\n| [multi-platform-campaign.json](./multi-platform-campaign.json) | Per-channel bodies + settings |\n\nPer-channel feature matrices and CLI flags: `../{identifier}-examples.md`, [provider-settings.md](../provider-settings.md), and [plugs.md](../plugs.md).\n\nFile v1.0.9:resources/facebook-examples.md\n\n# Facebook Page — CLI examples\n\n```bash\nFB_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"facebook\") | .id')\nopenquok integrations:settings \"$FB_ID\"\n```\n\nRun `integrations:settings` for `output.rules`, `output.maxLength`, and allow-listed `output.tools`. Publish keys below are stable for the Facebook Page provider.\n\nSettings mechanics: [provider-settings.md](./provider-settings.md). JSON recipes: [examples/EXAMPLES.md](./examples/EXAMPLES.md#facebook-page).\n\n## Supported features\n\n| Feature | Supported | Notes |\n| --- | --- | --- |\n| Text feed post | Yes | `-c` only |\n| Link preview | Yes | Optional `url` in settings; **ignored when photos or video are attached** |\n| Single photo | Yes | One uploaded image via `-m` |\n| Multi-photo carousel | Yes | Multiple `-m` attachments in one post |\n| Reel (MP4 video) | Yes | Single `.mp4` → Page video API; Facebook surfaces eligible uploads as Reels |\n| Facebook Stories | Yes | `post_type: story` or `facebook.postType: story`; image or MP4 required; each attachment → its own Story |\n| Follow-up comments | Yes | `facebook.replies` — optional one image per reply (feed posts only; not Stories) |\n| Page analytics | Yes | `analytics:platform` and `analytics:post` |\n| Personal profile / Groups | No | Pages you manage via Graph API only |\n\n## Agent tasks\n\n| User wants to… | JSON example |\n| --- | --- |\n| Post text to the Page | [facebook-text-only.json](./examples/facebook-text-only.json) |\n| Share a link with preview card | [facebook-link-preview.json](./examples/facebook-link-preview.json) |\n| Post a photo | [facebook-with-image.json](./examples/facebook-with-image.json) |\n| Post multiple photos | [facebook-multi-photo.json](./examples/facebook-multi-photo.json) |\n| Publish a Reel from MP4 | [facebook-reel.json](./examples/facebook-reel.json) |\n| Publish a Story (image or MP4) | [facebook-story.json](./examples/facebook-story.json) |\n| Add a comment after the post goes live | [facebook-follow-up-comment.json](./examples/facebook-follow-up-comment.json) |\n| Add a comment with one image after publish | [facebook-follow-up-comment-with-image.json](./examples/facebook-follow-up-comment-with-image.json) |\n| See what the Page supports | `openquok integrations:settings \"$FB_ID\"` |\n| Track Page performance | [Discover integration](#discover-integration) → `analytics:platform` |\n\n## Provider settings\n\nFlat JSON on `--settings` or inside `--providerSettingsByIntegrationId` for the Page UUID.\n\n| Key | Values | When |\n| --- | --- | --- |\n| `post_type` / `postType` | `post` (default) or `story` | Feed/Reel vs Story surface |\n| `facebook.postType` | `post` or `story` | Same as `post_type` (web composer bucket; API accepts both) |\n| `url` | `https://…` string | Text-only post with link-preview card |\n| `facebook.url` | `https://…` | Same as `url` (web composer bucket; API accepts both) |\n| `facebook.replies` | `[{ \"id\": \"…\", \"message\": \"…\", \"delaySeconds\": 60, \"media\": [...] }]` | Follow-up comments after publish (feed posts only; nested bucket in JSON) |\n\n**Rules:** Link `url` applies only when **no** media is attached and post type is `post`. With `-m`, the post uses attached photos or video instead of a link card. **Stories** require at least one image or MP4; each attachment publishes as its own Story. Follow-up `replies` are not supported for Stories.\n\n### Follow-up comments (`facebook.replies`)\n\nSame-account comments on the main post use the **`facebook`** bucket — not `threads.replies`.\n\nEach reply row:\n\n```json\n{\n  \"id\": \"reply-1\",\n  \"message\": \"First comment on the post\",\n  \"delaySeconds\": 60,\n  \"media\": [{ \"id\": \"<media-id>\", \"path\": \"https://cdn.example.com/reply.jpg\" }]\n}\n```\n\n- `delaySeconds` — wait after the previous part publishes (`0` = immediately after the prior step).\n- `media` — optional. Max **one image** per reply; **no video**. Upload first (Rule 2) before referencing `id` / `path`. Omit `media` for text-only comments.\n\nText-only recipe: [facebook-follow-up-comment.json](./examples/facebook-follow-up-comment.json). With one image on a reply row: [facebook-follow-up-comment-with-image.json](./examples/facebook-follow-up-comment-with-image.json). Mechanics: [provider-settings.md](./provider-settings.md#scheduled-follow-up-replies).\n\n**Follow-up with one image** (upload first, then nest under `facebook.replies`):\n\n```bash\nREPLY_MEDIA=$(openquok upload ./comment-image.jpg | jq -c '[{id: .data.id, path: (.data.path // .data.filePath)}]')\n\nopenquok posts:create \\\n  -s \"2026-01-01T12:00:00Z\" \\\n  -c \"Main post\" \\\n  -i \"$FB_ID\" \\\n  --providerSettingsByIntegrationId \"$(jq -nc --arg id \"$FB_ID\" --argjson media \"$REPLY_MEDIA\" '\n    { ($id): { facebook: { replies: [\n      { id: \"reply-1\", message: \"See the chart in this comment\", delaySeconds: 60, media: $media }\n    ] } } }\n  ')\"\n```\n\n## Run an example\n\n```bash\nopenquok posts:create --json ./examples/facebook-link-preview.json\n```\n\nAt publish time the backend resolves each stored object key to a public `https://` URL for Meta to fetch.\n\n## Discover integration\n\n```bash\nopenquok integrations:settings \"$FB_ID\"\nopenquok analytics:platform \"$FB_ID\" -d 30\n```\n\n## Post insights\n\n```bash\nPOST_ID=$(openquok posts:list | jq -r '.items[0].id')\nopenquok analytics:post \"$POST_ID\" -d 7\n```\n\nFile v1.0.9:resources/instagram-business-examples.md\n\n# Instagram — business (`instagram-business`)\n\nProfessional Instagram account connected via **Facebook Login for Business** (Page-linked). Confirm keys with `integrations:settings` for your workspace row.\n\n```bash\nIG_BUSINESS_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"instagram-business\") | .id')\nopenquok integrations:settings \"$IG_BUSINESS_ID\"\n```\n\nPosting behavior matches **Instagram (Standalone)** — only OAuth and token host differ. See [instagram-standalone-examples.md](./instagram-standalone-examples.md) for the same recipes with `instagram-standalone`.\n\nSettings mechanics: [provider-settings.md](./provider-settings.md). JSON recipes: [examples/EXAMPLES.md](./examples/EXAMPLES.md#instagram).\n\n## Agent tasks\n\n| User wants to… | JSON example |\n| --- | --- |\n| Post a feed image | [instagram-feed-post.json](./examples/instagram-feed-post.json) |\n| Post a carousel | [instagram-carousel.json](./examples/instagram-carousel.json) |\n| Publish a Reel | [instagram-reel.json](./examples/instagram-reel.json) |\n| Publish a Story | [instagram-story.json](./examples/instagram-story.json) |\n| Test a Trial Reel with collaborators | [instagram-trial-reel.json](./examples/instagram-trial-reel.json) |\n| Add text comments after publish | [instagram-follow-up-comments.json](./examples/instagram-follow-up-comments.json) |\n| Check limits and tools | `openquok integrations:settings \"$IG_BUSINESS_ID\"` |\n\n## Supported features\n\n| Feature | Supported | Notes |\n| --- | --- | --- |\n| Feed image post | Yes | At least one attachment required for `scheduled` |\n| Carousel (2–10 items) | Yes | Auto when `-m` has multiple attachments and `post_type` is not `story` |\n| Reel (single video) | Yes | One `.mp4` attachment → Reels surface |\n| Story | Yes | `post_type: \"story\"`; one attachment; no collaborators |\n| Trial Reel | Yes | `is_trial_reel` + single MP4; not combinable with Stories |\n| Collaborators (max 3) | Yes | Feed/Reel **single** media only — not carousel, not Stories |\n| Graduation strategy | Yes | `MANUAL` or `SS_PERFORMANCE` when `is_trial_reel` is true |\n| Text follow-up comments | Yes | `instagram.replies` in provider settings |\n| Story link stickers | No | — |\n| Automatic inbox / keyword replies | No | Not visitor-comment or DM bots; use `instagram.replies` for scheduled follow-ups on your post |\n| Plugs (internal, cross-account, global) | No | Instagram not in automations/plugs matrix |\n\n## Provider settings (`--settings`)\n\nFlat JSON merged into `providerSettingsByIntegrationId` for each `-i` UUID. Run `integrations:settings` to confirm allow-listed keys in your workspace.\n\n| Key | Values | Default | When |\n| --- | --- | --- | --- |\n| `post_type` | `\"post\"` \\| `\"story\"` | `\"post\"` | Story vs feed/Reel |\n| `is_trial_reel` | `true` \\| `false` | `false` | Trial Reel (feed only, one video) |\n| `graduation_strategy` | `\"MANUAL\"` \\| `\"SS_PERFORMANCE\"` | `\"MANUAL\"` | Trial Reel graduation |\n| `collaborators` | `[\"user1\",\"user2\"]` or `[{\"label\":\"user1\"}]` | `[]` | Max 3; not with carousel or Stories |\n| `instagram.replies` | `[{ \"id\": \"…\", \"message\": \"…\", \"delaySeconds\": 60 }]` | `[]` | Scheduled text comments (nested bucket in JSON) |\n\n## Run an example\n\nUse the same JSON files with an `instagram-business` integration UUID:\n\n```bash\nopenquok posts:create --json ./examples/instagram-feed-post.json\n```\n\nFile v1.0.9:resources/instagram-standalone-examples.md\n\n# Instagram — standalone (`instagram-standalone`)\n\nProfessional Instagram account connected via **Instagram Login** (no Facebook Page required).\n\n```bash\nIG_STANDALONE_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"instagram-standalone\") | .id')\nopenquok integrations:settings \"$IG_STANDALONE_ID\"\n```\n\nAlways run `integrations:settings` for required fields and allow-listed `output.tools` before posting. Posting behavior matches **Instagram (Business)** — see [instagram-business-examples.md](./instagram-business-examples.md) for the same feature matrix with `instagram-business`.\n\nSettings mechanics: [provider-settings.md](./provider-settings.md). JSON recipes: [examples/EXAMPLES.md](./examples/EXAMPLES.md#instagram).\n\n## Agent tasks\n\n| User wants to… | JSON example |\n| --- | --- |\n| Post a feed image | [instagram-feed-post.json](./examples/instagram-feed-post.json) |\n| Post a carousel | [instagram-carousel.json](./examples/instagram-carousel.json) |\n| Publish a Reel | [instagram-reel.json](./examples/instagram-reel.json) |\n| Publish a Story | [instagram-story.json](./examples/instagram-story.json) |\n| Test a Trial Reel with collaborators | [instagram-trial-reel.json](./examples/instagram-trial-reel.json) |\n| Add text comments after publish | [instagram-follow-up-comments.json](./examples/instagram-follow-up-comments.json) |\n| Check limits and tools | `openquok integrations:settings \"$IG_STANDALONE_ID\"` |\n\n## Supported features\n\n| Feature | Supported | Notes |\n| --- | --- | --- |\n| Feed image post | Yes | At least one attachment required for `scheduled` |\n| Carousel (2–10 items) | Yes | Auto when `-m` has multiple attachments and `post_type` is not `story` |\n| Reel (single video) | Yes | One `.mp4` attachment → Reels surface |\n| Story | Yes | `post_type: \"story\"`; one attachment; no collaborators |\n| Trial Reel | Yes | `is_trial_reel` + single MP4; not combinable with Stories |\n| Collaborators (max 3) | Yes | Feed/Reel **single** media only — not carousel, not Stories |\n| Graduation strategy | Yes | `MANUAL` or `SS_PERFORMANCE` when `is_trial_reel` is true |\n| Text follow-up comments | Yes | `instagram.replies` in provider settings |\n| Story link stickers | No | — |\n| Automatic inbox / keyword replies | No | Not visitor-comment or DM bots; use `instagram.replies` for scheduled follow-ups on your post |\n| Plugs (internal, cross-account, global) | No | Instagram not in automations/plugs matrix |\n\n## Provider settings (`--settings`)\n\nFlat JSON merged into `providerSettingsByIntegrationId` for each `-i` UUID.\n\n| Key | Values | Default | When |\n| --- | --- | --- | --- |\n| `post_type` | `\"post\"` \\| `\"story\"` | `\"post\"` | Story vs feed/Reel |\n| `is_trial_reel` | `true` \\| `false` | `false` | Trial Reel (feed only, one video) |\n| `graduation_strategy` | `\"MANUAL\"` \\| `\"SS_PERFORMANCE\"` | `\"MANUAL\"` | Trial Reel graduation |\n| `collaborators` | `[\"user1\",\"user2\"]` or `[{\"label\":\"user1\"}]` | `[]` | Max 3; not with carousel or Stories |\n| `instagram.replies` | `[{ \"id\": \"…\", \"message\": \"…\", \"delaySeconds\": 60 }]` | `[]` | Scheduled text comments (nested bucket in JSON) |\n\n## Run an example\n\nUse the same JSON files with an `instagram-standalone` integration UUID:\n\n```bash\nopenquok posts:create --json ./examples/instagram-feed-post.json\n```\n\nFile v1.0.9:resources/linkedin-examples.md\n\n# LinkedIn (`linkedin`)\n\nPersonal professional profile channel. Single-step OAuth.\n\nJSON recipes: [examples/EXAMPLES.md](./examples/EXAMPLES.md#linkedin). Settings mechanics: [provider-settings.md](./provider-settings.md).\n\n## Supported features\n\n| Feature | Supported |\n| --- | --- |\n| Text posts (3,000 chars) | Yes |\n| Single / multi-image | Yes |\n| MP4 video (one attachment) | Yes |\n| Image → PDF document carousel | Yes (≥2 images, no video) |\n| Follow-up text comments | Yes — `linkedin.replies`; text only (no media on follow-ups) |\n| Cross-account comment / reshare (internal plugs) | Yes (`linkedin.crossAccountPlugs`) |\n| Account / post analytics | No (Page only) |\n\n## Agent tasks\n\n| User intent | JSON example |\n| --- | --- |\n| Connect personal LinkedIn | Setup in human docs; identifier `linkedin` |\n| Schedule a text post | [linkedin-text-post.json](./examples/linkedin-text-post.json) |\n| Post with video | [linkedin-with-video.json](./examples/linkedin-with-video.json) |\n| Image → PDF document carousel | [linkedin-document-carousel.json](./examples/linkedin-document-carousel.json) |\n| Add a comment after publish | [linkedin-follow-up-comment.json](./examples/linkedin-follow-up-comment.json) |\n| Comment or reshare from other LinkedIn channels (internal plug) | `linkedin.crossAccountPlugs` — see [plugs.md](./plugs.md) |\n\nFor Page document carousels and analytics, use `linkedin-page` — see [linkedin-page-examples.md](./linkedin-page-examples.md).\n\n## Provider settings\n\n| Key (flat CLI) | Nested web bucket | Purpose |\n| --- | --- | --- |\n| `post_as_images_carousel` | `linkedin.postAsImagesCarousel` | Convert ≥2 images to PDF document (no video) |\n| `carousel_name` | `linkedin.carouselName` | PDF title (default `slides`) |\n| `linkedin.replies` | `linkedin.replies` | Text follow-up comments after publish (no `media` on reply rows) |\n| `linkedin.crossAccountPlugs` | `linkedin.crossAccountPlugs` | Cross-account comment (`linkedin-add-comment`) or reshare (`linkedin-repost-post-users`) |\n\nFlat keys work on `--settings` or inside `--providerSettingsByIntegrationId`. Prefer the nested `linkedin.*` bucket in JSON files (matches composer).\n\n### Follow-up comments (`linkedin.replies`)\n\nSame-account comments on the main post live under the **`linkedin`** bucket — including **`linkedin-page`** integrations (alias bucket, not `threads.replies`).\n\nEach reply row:\n\n```json\n{ \"id\": \"reply-1\", \"message\": \"Follow-up comment on the post\", \"delaySeconds\": 60 }\n```\n\n- `delaySeconds` — wait after the previous part publishes (`0` = immediately after the prior step).\n- **No `media`** — put images and video on the main post only. LinkedIn follow-ups are text-only in the composer and at publish time.\n\nCopy-paste recipe: [linkedin-follow-up-comment.json](./examples/linkedin-follow-up-comment.json). Mechanics: [provider-settings.md](./provider-settings.md#scheduled-follow-up-replies).\n\nCross-account shape: [provider-settings.md](./provider-settings.md#internal-plugs). Plug catalog: [plugs.md](./plugs.md).\n\n## Run an example\n\nReplace `<integration-id>` and media paths with values from `openquok integrations:list` and `openquok upload`.\n\n```bash\nopenquok integrations:list --provider linkedin\nopenquok posts:create --json ./examples/linkedin-document-carousel.json\n```\n\nFlat CLI equivalent for document carousel:\n\n```bash\nopenquok posts:create \\\n  -i \"<integration-id>\" \\\n  -c \"Swipe through our latest slides.\" \\\n  -s \"2026-06-22T10:00:00.000Z\" \\\n  --settings '{\"post_as_images_carousel\":true,\"carousel_name\":\"June deck\"}' \\\n  -m '[{\"id\":\"<media-id-1>\",\"path\":\"https://cdn.example.com/slide-1.jpg\"},{\"id\":\"<media-id-2>\",\"path\":\"https://cdn.example.com/slide-2.jpg\"}]'\n```\n\nFile v1.0.9:resources/linkedin-page-examples.md\n\n# LinkedIn Page (`linkedin-page`)\n\nCompany Page channel. Two-step OAuth (login, then Page picker).\n\nJSON recipes: [examples/EXAMPLES.md](./examples/EXAMPLES.md#linkedin). Settings mechanics: [provider-settings.md](./provider-settings.md).\n\n## Supported features\n\n| Feature | Supported |\n| --- | --- |\n| Text posts (3,000 chars) | Yes |\n| Single / multi-image | Yes |\n| MP4 video (one attachment) | Yes |\n| Image → PDF document carousel | Yes (≥2 images, no video) |\n| Follow-up text comments | Yes |\n| Cross-account comment / reshare (internal plugs) | Yes (`linkedin.crossAccountPlugs`) |\n| Global plugs (likes threshold) | Yes — `plugs:*` CLI or web **Account → Plugs** |\n| Account analytics | Yes |\n| Per-post analytics | Yes |\n\n## Agent tasks\n\n| User intent | JSON example |\n| --- | --- |\n| Connect a company Page | OAuth `linkedin-page` + Page picker |\n| Schedule slide deck / carousel | [linkedin-page-document-carousel.json](./examples/linkedin-page-document-carousel.json) |\n| Pull Page insights | `analytics:platform` (see below) |\n| Set global plug rules (auto repost / comment at likes threshold) | `plugs:upsert` — see [plugs.md](./plugs.md) |\n\n## Provider settings\n\n| Key (flat CLI) | Nested web bucket | Purpose |\n| --- | --- | --- |\n| `post_as_images_carousel` | `linkedin.postAsImagesCarousel` | Convert images to PDF document |\n| `carousel_name` | `linkedin.carouselName` | PDF title (default `slides`) |\n| `linkedin.crossAccountPlugs` | `linkedin.crossAccountPlugs` | Cross-account comment or reshare — see [plugs.md](./plugs.md) |\n\n## Run an example\n\n```bash\nopenquok integrations:list --provider linkedin-page\nopenquok posts:create --json ./examples/linkedin-page-document-carousel.json\nopenquok analytics:platform -i \"<integration-id>\" -d 30\n```\n\nFlat CLI equivalent:\n\n```bash\nopenquok posts:create \\\n  -i \"<integration-id>\" \\\n  -c \"Our Q2 product slides — swipe through the deck.\" \\\n  -s \"2026-06-22T10:00:00.000Z\" \\\n  -j '{\"providerSettingsByIntegrationId\":{\"<integration-id>\":{\"linkedin\":{\"postAsImagesCarousel\":true,\"carouselName\":\"Q2 update\"}}}}'\n```\n\nFile v1.0.9:resources/patterns.md\n\n# Workflow recipes\n\nExtended `openquok` patterns. Rules and auth: [SKILL.md](../SKILL.md). Commands: [command-reference.md](./command-reference.md). Per-channel features and publish settings: [provider-settings.md](./provider-settings.md) and `*-examples.md`. Plugs (internal + global): [plugs.md](./plugs.md).\n\n## Resolve integration UUIDs\n\n```bash\nopenquok integrations:list | jq -r '.[] | {id, identifier}'\nopenquok integrations:settings <integration-uuid>\n```\n\nMeta channels today: `threads`, `facebook`, `instagram-standalone`, `instagram-business`. LinkedIn: `linkedin`, `linkedin-page`. Dev.to: `devto` (`tags`, `organizations`). Call `integrations:trigger` only for `methodName` values listed under `output.tools`.\n\n## Allow-listed provider tools\n\n```bash\nTH_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"threads\") | .id')\nopenquok integrations:settings \"$TH_ID\"\nopenquok integrations:trigger \"$TH_ID\" <method-from-settings> -d '{}'\n```\n\nReplace `<method-from-settings>` and `-d` using `output.tools[].methodName` and `dataSchema`. Dev.to examples:\n\n```bash\nDEVTO_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"devto\") | .id')\nopenquok integrations:trigger \"$DEVTO_ID\" tags\nopenquok integrations:trigger \"$DEVTO_ID\" organizations\n```\n\nLinkedIn `company` needs a URL payload:\n\n```bash\nLI_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"linkedin\") | .id')\nopenquok integrations:trigger \"$LI_ID\" company -d '{\"url\":\"https://www.linkedin.com/company/example\"}'\n```\n\n## Multiple attachments\n\n```bash\nMEDIA=$(jq -s 'add' \\\n  <(openquok upload ./a.jpg | jq '[{id: .data.id, path: (.data.path // .data.filePath)}]') \\\n  <(openquok upload ./b.jpg | jq '[{id: .data.id, path: (.data.path // .data.filePath)}]'))\nopenquok posts:create -c \"…\" -m \"$MEDIA\" -s \"2026-01-01T12:00:00Z\" -i \"<uuid>\"\n```\n\n## Multi-channel campaign (JSON file)\n\nUse [examples/multi-platform-campaign.json](./examples/multi-platform-campaign.json) — per-channel bodies and `providerSettingsByIntegrationId`.\n\n```bash\nopenquok posts:create --json ./examples/multi-platform-campaign.json\n```\n\n## Enforce max length\n\n```bash\nINTEGRATION_ID=\"<uuid>\"\nCONTENT=\"Your caption\"\nMAX=$(openquok integrations:settings \"$INTEGRATION_ID\" | jq '.output.maxLength')\n# Truncate CONTENT when ${#CONTENT} -gt MAX before posts:create\n```\n\n## Batch schedule\n\nLoop `openquok upload` + `posts:create` per slot; reuse one integration UUID; vary `-s` and `-c` per iteration.\n\n## Internal plugs on scheduled posts\n\nAttach internal plugs when creating posts — same-account Threads reply or cross-account comment/repost/reshare. Use `providerSettingsByIntegrationId` with the channel bucket (`threads`, `x`, `linkedin`). Examples: [threads-engagement-plug.json](./examples/threads-engagement-plug.json), [threads-cross-account-plug.json](./examples/threads-cross-account-plug.json), [x-cross-account-repost.json](./examples/x-cross-account-repost.json). Catalog: [plugs.md](./plugs.md).\n\n## Global plugs on channels\n\n```bash\nopenquok plugs:catalog\nopenquok plugs:list <integration-id>\nopenquok plugs:upsert <integration-id> --func autoPlugPost \\\n  --fields '[{\"name\":\"likesAmount\",\"value\":\"100\"},{\"name\":\"post\",\"value\":\"Grab the link in bio!\"}]'\n```\n\nSee [plugs.md](./plugs.md) for provider matrix and `plugs:activate` / `plugs:delete`.\n\n## Retry on transient failure\n\nRetry `posts:create` with exponential backoff (e.g. 2s, 4s, 8s) up to a fixed attempt cap; surface the last stderr/stdout to the user.\n\nArchive v1.0.8: 62 files, 60797 bytes\n\nFiles: resources/command-reference.md (8027b), resources/devto-examples.md (4618b), resources/examples/devto-article-title-tags.json (508b), resources/examples/devto-canonical.json (505b), resources/examples/devto-organization.json (515b), resources/examples/devto-series.json (413b), resources/examples/EXAMPLES.md (5902b), resources/examples/facebook-follow-up-comment-with-image.json (519b), resources/examples/facebook-follow-up-comment.json (363b), resources/examples/facebook-link-preview.json (269b), resources/examples/facebook-multi-photo.json (308b), resources/examples/facebook-reel.json (230b), resources/examples/facebook-story.json (314b), resources/examples/facebook-text-only.json (148b), resources/examples/facebook-with-image.json (222b), resources/examples/instagram-carousel.json (424b), resources/examples/instagram-feed-post.json (329b), resources/examples/instagram-follow-up-comments.json (529b), resources/examples/instagram-reel.json (218b), resources/examples/instagram-story.json (314b), resources/examples/instagram-trial-reel.json (465b), resources/examples/linkedin-document-carousel.json (587b), resources/examples/linkedin-follow-up-comment.json (367b), resources/examples/linkedin-page-document-carousel.json (527b), resources/examples/linkedin-text-post.json (138b), resources/examples/linkedin-with-video.json (243b), resources/examples/multi-platform-campaign.json (988b), resources/examples/threads-cross-account-plug.json (612b), resources/examples/threads-engagement-plug.json (436b), resources/examples/threads-follow-up-replies.json (476b), resources/examples/threads-follow-up-reply-with-image.json (533b), resources/examples/threads-media-carousel.json (301b), resources/examples/threads-text-only.json (140b), resources/examples/threads-thread-finisher.json (474b), resources/examples/threads-with-image.json (228b), resources/examples/tiktok-photo-carousel.json (527b), resources/examples/tiktok-private-draft.json (626b), resources/examples/tiktok-upload-inbox.json (460b), resources/examples/tiktok-video-direct-post.json (485b), resources/examples/x-cross-account-repost.json (501b), resources/examples/x-follow-up-replies.json (349b), resources/examples/x-follow-up-reply-with-image.json (494b), resources/examples/youtube-flat-settings.json (426b), resources/examples/youtube-video-title-privacy.json (444b), resources/examples/youtube-with-tags.json (579b), resources/examples/youtube-with-thumbnail.json (486b), resources/facebook-examples.md (5302b), resources/instagram-business-examples.md (3193b), resources/instagram-standalone-examples.md (3135b), resources/linkedin-examples.md (3720b), resources/linkedin-page-examples.md (2091b), resources/patterns.md (3515b), resources/plugs.md (4828b), resources/provider-settings.md (11803b), resources/threads-examples.md (6961b), resources/threads-publish.md (2586b), resources/tiktok-examples.md (7439b), resources/x-examples.md (6015b), resources/youtube-examples.md (3647b), skill-card.md (2708b), SKILL.md (15498b), _meta.json (132b)\n\nFile v1.0.8:SKILL.md\n\n---\nname: openquok-core\ndescription: >-\n  Schedule and manage social posts with the openquok CLI — authenticate, upload media, create drafts and scheduled posts, configure internal plugs, and read channel analytics for integrations in your OpenQuok workspace.\nhomepage: https://www.npmjs.com/package/@openquok/auto-cli\nversion: 1.0.0\nlicense: MIT\ncompatibility: Requires the global openquok CLI on PATH (see homepage). Installing this skill does not add the binary.\nprerequisites:\n  commands: [openquok]\nmetadata: {\"openclaw\":{\"emoji\":\"📮\",\"always\":true,\"requires\":{\"bins\":[\"openquok\"]},\"homepage\":\"https://www.npmjs.com/package/@openquok/auto-cli\"},\"hermes\":{\"tags\":[\"social-media\",\"openquok\",\"scheduling\"],\"category\":\"social-media\",\"requires_toolsets\":[\"terminal\"]},\"grok-bot\":{\"tags\":[\"social-media\",\"openquok\",\"scheduling\"],\"category\":\"social-media\",\"requires_toolsets\":[\"terminal\"],\"workspace_skill_path\":\"/workspace/openquok-core/SKILL.md\"},\"thinkrail\":{\"tags\":[\"social-media\",\"openquok\",\"scheduling\"],\"category\":\"social-media\",\"requires_toolsets\":[\"terminal\"],\"skill_paths\":[\"~/.pi/agent/skills/openquok-core/SKILL.md\",\".pi/skills/openquok-core/SKILL.md\"]}}\n---\n\n<!-- SPDX-FileCopyrightText: 2026 Rati Montreewat -->\n<!-- SPDX-License-Identifier: MIT -->\n\n## Session opening (first turn after reset)\n\n**When:** first assistant reply after `/new`, `/reset`, a new channel thread, or a “new session started” notice.\n\n**On that turn only:** use the OpenQuok bot voice below instead of a generic host welcome. Do **not** reuse this block on later turns.\n\n**One message only.** Run shell (below), then send **exactly one** assistant message. Forbidden on this turn:\n\n- A persona line before tools (e.g. “Hello, … I’m Atlas … What should we focus on?”).\n- A second message with only CLI version (e.g. “The OpenQuok CLI version is 0.0.6.”).\n- Repeating the host greeting after the system “new session started” line.\n\n**Shell (before any user-visible text):**\n\n```bash\nopenquok --version\nopenquok auth:status\n```\n\nIf `auth:status` shows `\"connected\": true`, also run `openquok auth:workspace`.\n\n**Required opening sentence (verbatim start):** `Hi, I am the OpenQuok bot.`\n\n**Same message must also include:**\n\n1. Installed CLI version from `openquok --version`.\n2. If the user may be on an old build: note that skill install does not upgrade the CLI and offer to walk through upgrade using the [CLI package page](https://www.npmjs.com/package/@openquok/auto-cli) — only after they agree.\n3. Auth: if connected, say you are authenticated and name **`workspace.name`**; if not, say not authenticated and offer the **two-step device flow** (below) or a programmatic token (`opo_`). **Never** run `auth:login --json` without `--no-poll` on messaging hosts — the shell exits before credentials are stored.\n\n**Fill-in template (one paragraph — replace `…` from shell output):**\n\n> Hi, I am the OpenQuok bot. OpenQuok CLI is …. [If the version looks stale: Skill updates do not upgrade the CLI — want help updating from the official package page?] [If connected: You're authenticated; workspace is …. | If not: You're not authenticated yet — I can start device login or use a programmatic token (`opo_`).]\n\nAfter this opening message, normal persona and task help are fine. Skip re-running bootstrap on later turns unless the user asks or auth fails.\n\n| Property | Value |\n|----------|-------|\n| **name** | openquok |\n| **description** | AI-ready social scheduling via the `openquok` CLI (global binary — separate from this skill): posts, integrations, media, analytics. |\n| **allowed-tools** | Bash(openquok:*) |\n\n---\n\n## ⚠️ Hard Rules (Read First)\n\n**0 — Session opening.** Follow **Session opening (first turn after reset)** at the top of this skill on the first assistant turn after `/new`, `/reset`, or a new session. Skills do not install or upgrade the `openquok` binary.\n\n**Links:** [npm `@openquok/auto-cli`](https://www.npmjs.com/package/@openquok/auto-cli) · [monorepo](https://github.com/Ratimon/openquok-monorepo/) · [CLI package](https://github.com/Ratimon/openquok-monorepo/tree/main/agent) · [openquok.com](https://www.openquok.com/)\n\n**1 — Auth before API work.** Any command that calls the API needs valid credentials. After bootstrap, re-check only when a command fails with auth errors.\n\n**2 — Media via workspace upload.** Every `-m` / `--media` / JSON `media[]` entry must be `{id, path}` from `openquok upload` or `openquok upload-from-url`. Never pass raw local paths or bare CDN URLs.\n\n```bash\nmedia_json() { openquok upload \"$1\" | jq -c '[{id: .data.id, path: (.data.path // .data.filePath)}]'; }\nopenquok posts:create -c \"…\" -s \"2026-01-01T12:00:00Z\" -i \"<uuid>\" -m \"$(media_json ./photo.jpg)\"\n```\n\nVerify upload stdout with `jq` (require `data.id` and `data.filePath`). Pass `filePath` as `media[].path`. Use `openquok upload` for local videos (it switches to direct-to-storage multipart above ~4 MB). Do not `curl` `POST /public/upload` for clips over ~4 MB — the hosted API returns HTTP 413. Remote assets: `openquok upload-from-url \"https://…\"`.\n\n---\n\n## Authentication\n\n| Order | Path | Use |\n|-------|------|-----|\n| 1 | **Device OAuth (two steps)** | Messaging agents (Telegram/Hermes): `auth:login --json --no-poll` → user opens `verification_uri_complete` → `auth:login:poll --device-code <device_code>` → `auth:status` |\n| 2 | **Programmatic token** | Headless or when device flow fails: `export OPENQUOK_API_KEY=opo_…` or `openquok auth:login --apiKey \"opo_…\"` |\n\n**Device OAuth on messaging hosts (required two-step):**\n\n```bash\nopenquok auth:login --json --no-poll\n# send verification_uri_complete to the user; wait until they confirm they authorized\nopenquok auth:login:poll --device-code \"<device_code from stdout>\"\nopenquok auth:status\n```\n\n- Tokens: [OpenQuok dashboard](https://www.openquok.com/) → **Settings → Developers → Access** → **Generate / Rotate token** (shown once).\n- Never invent verification URLs, user codes, or `device_code` — only values from `auth:login --json --no-poll` stdout.\n- Do **not** use `auth:login --json` alone on Telegram/Hermes; the host stops the shell after the first JSON and `~/.openquok/credentials.json` is never written.\n- Disk credentials in `~/.openquok/credentials.json` take precedence over `OPENQUOK_API_KEY` until `auth:logout`.\n- Workspace context: `openquok auth:workspace` → `{ workspace: { id, name } }`.\n- Optional: `OPENQUOK_API_URL`, `OPENQUOK_AUTH_SERVER` (local dev: `http://localhost:3111`).\n\nDetails: [resources/command-reference.md](./resources/command-reference.md#authentication).\n\n---\n\n## Shell safety\n\n- Run **fixed** `openquok` invocations; do not build commands by concatenating untrusted chat text into the shell.\n- Put captions and JSON payloads in **quoted** flags, heredocs, or files — not bare `$USER_INPUT` expansions.\n- Treat integration UUIDs, post IDs, and schedule times as opaque strings; reject values with shell metacharacters before use.\n\n---\n\n## Workflow\n\n| Step | Action |\n|------|--------|\n| 1 | Session opening (Rule 0): shell version/auth check, then one OpenQuok-bot greeting |\n| 2 | `openquok integrations:groups` when the workspace uses channel groups; then `integrations:list` (optionally `--group <id>`) → `integrations:settings <uuid>` per channel |\n| 3 | `integrations:trigger <uuid> <method> -d '{}'` when `output.tools` requires it |\n| 4 | `upload` / `upload-from-url` for media; ask user for file or direct image URL if missing in chat |\n| 5 | `posts:create` / `posts:status` / `posts:reschedule`; use `posts:status` to flip draft ↔ scheduled at the same time; use `posts:reschedule` to move the publish slot; agent drafts: `-t draft` + `--note`; TikTok inbox/private drafts: `--note` with finish-in-app checklist; update with `posts:review-todo` |\n| 6 | `analytics:platform` / `analytics:post` with `-d 7` \\| `30` \\| `90` |\n| 7 | Missing release id: `posts:missing` → `posts:connect --release-id` |\n\nConnect new channels in the web app; the CLI only uses UUIDs from `integrations:list`.\n\n### Integration discovery\n\n```bash\nopenquok integrations:list\nopenquok integrations:list --group <customer-group-id>\nopenquok integrations:groups\nopenquok integrations:settings <integration-uuid>\nopenquok integrations:trigger <integration-uuid> <method-name> -d '{}'\n```\n\nUse `integrations:groups` to list channel groups (`{id, name}`), then filter channels with `integrations:list --group`. Full flag reference: [resources/command-reference.md](./resources/command-reference.md#integrations).\n\n---\n\n## Posting essentials\n\n```bash\n# Scheduled post\nopenquok posts:create -c \"Caption\" -s \"2026-01-01T12:00:00Z\" -i \"<uuid>\"\n\n# Draft + human checklist\nopenquok posts:create -c \"…\" -s \"…\" -t draft -i \"<uuid>\" --note \"Check CTA before schedule\"\n\n# Per-channel captions (multi integration)\nopenquok posts:create -s \"…\" -i \"<uuid-a>,<uuid-b>\" \\\n  --bodiesByIntegrationId '{\"<uuid-a>\":\"Short\",\"<uuid-b>\":\"Long\"}'\n\n# Provider fields (confirm keys via integrations:settings)\nopenquok posts:create -c \"…\" -s \"…\" --settings '{\"post_type\":\"post\"}' -i \"<uuid>\"\n\n# Full API body\nopenquok posts:create --json ./examples/threads-text-only.json\n```\n\n- Flag-based create **requires** `-s` (ISO-8601) unless `--json` includes `scheduledAt`.\n- `posts:status` flips draft ↔ scheduled at the stored time; `posts:reschedule` moves the publish slot (`-s`). Full flags: [resources/command-reference.md](./resources/command-reference.md#postsreschedule).\n- `--settings` merges into `providerSettingsByIntegrationId` for each `-i` UUID; per-UUID maps use `--providerSettingsByIntegrationId`. See [resources/provider-settings.md](./resources/provider-settings.md).\n- Repeated `-c` (+ optional `-m`, `-d` in **milliseconds**) can build follow-up segments — for Meta Threads/Instagram follow-ups prefer nested `threads` / `instagram` buckets in channel examples.\n\nCommand surface: [resources/command-reference.md](./resources/command-reference.md).\n\n---\n\n## Plugs (internal and global)\n\nOpenQuok automates post-publish engagement with two plug types (included on paid plans):\n\n| Type | What it does | CLI |\n| --- | --- | --- |\n| **Internal plugs** | Same-account delayed reply (Threads) or actions from other connected channels (comment, repost, reshare) | Yes — set on `posts:create` via `providerSettingsByIntegrationId` |\n| **Global plugs** | Channel rules that trigger a reply/repost when likes hit a threshold (checks every 6h, up to 3 runs) | Yes — `plugs:catalog`, `plugs:list`, `plugs:upsert`, `plugs:activate`, `plugs:delete` |\n\nSupported channels: **Threads**, **X**, **LinkedIn**, **LinkedIn Page** (not Facebook, Instagram, YouTube, or TikTok).\n\n```bash\n# Internal plug — cross-account Threads comment (see examples/)\nopenquok posts:create --json ./examples/threads-cross-account-plug.json\n\n# Internal plug — same-account Threads delayed reply\nopenquok posts:create --json ./examples/threads-engagement-plug.json\n\n# Global plug — auto-reply when likes reach threshold (channel-level rule)\nopenquok plugs:catalog\nopenquok plugs:upsert <integration-id> --func autoPlugPost \\\n  --fields '[{\"name\":\"likesAmount\",\"value\":\"100\"},{\"name\":\"post\",\"value\":\"Thanks for reading!\"}]'\n```\n\nFull catalog, provider matrix, and global-plug web setup: [resources/plugs.md](./resources/plugs.md). Setting keys: [resources/provider-settings.md](./resources/provider-settings.md#internal-plugs).\n\n---\n\n## Channels (Meta)\n\nRun `integrations:settings <uuid>` for `rules`, `maxLength`, and `tools`. Match the user’s goal to the **Agent tasks** table in each channel file; publish keys and recipes are there.\n\nProvider settings overview: [resources/provider-settings.md](./resources/provider-settings.md).\n\n| Channel | `identifier` | User intents (see file) | Examples |\n|---------|----------------|-------------------------|----------|\n| Threads | `threads` | text/media/carousel, reply chain, finisher, internal plugs, global plugs, missing post | [threads-examples.md](./resources/threads-examples.md) |\n| Facebook Page | `facebook` | text, link preview, photo, carousel, Reel, comments | [facebook-examples.md](./resources/facebook-examples.md) |\n| Instagram Login | `instagram-standalone` | feed, carousel, Reel, Story, trial reel, comments | [instagram-standalone-examples.md](./resources/instagram-standalone-examples.md) |\n| Instagram Page | `instagram-business` | same as standalone (Page-linked OAuth) | [instagram-business-examples.md](./resources/instagram-business-examples.md) |\n| YouTube | `youtube` | MP4 upload, title/privacy/tags/thumbnail, channel analytics | [youtube-examples.md](./resources/youtube-examples.md) |\n| TikTok | `tiktok` | direct publish, inbox upload (`UPLOAD`), private `SELF_ONLY` drafts, privacy, toggles, analytics | [tiktok-examples.md](./resources/tiktok-examples.md) |\n| LinkedIn | `linkedin` | personal profile posts, images, video, text comments, internal plugs | [linkedin-examples.md](./resources/linkedin-examples.md) |\n| LinkedIn Page | `linkedin-page` | Page picker, document carousel, internal + global plugs, Page + post analytics | [linkedin-page-examples.md](./resources/linkedin-page-examples.md) |\n| X | `x` | text/media, thread replies, finisher, reply settings, internal + global plugs, analytics | [x-examples.md](./resources/x-examples.md) |\n| Dev.to | `devto` | markdown article, title/tags/cover/canonical/org/series, `tags` + `organizations` tools, analytics | [devto-examples.md](./resources/devto-examples.md) |\n\nThreads publish failures: [threads-publish.md](./resources/threads-publish.md).\n\n---\n\n## More recipes\n\n[resources/patterns.md](./resources/patterns.md) — multi-attachment posts, `integrations:trigger`, JSON campaigns, internal plugs, length checks, batching, retries.\n\n[resources/plugs.md](./resources/plugs.md) — internal plugs (CLI) and global plugs (web app).\n\n---\n\n## Pitfalls\n\n| Symptom | Fix |\n|---------|-----|\n| API 401 / auth errors | Two-step device OAuth (`auth:login --json --no-poll` then `auth:login:poll`); or programmatic token (`opo_`); never fake device URLs |\n| Device login OK in browser but CLI has no credentials | Messaging host ended `auth:login --json` before polling — use `--no-poll` + `auth:login:poll`, or `auth:login --apiKey` |\n| Invalid or expired device code | Re-run `auth:login --json --no-poll`; use fresh `verification_uri_complete` (~30 min) |\n| Wrong channel | Re-fetch UUID from `integrations:list` |\n| Media rejected at publish | Rule 2: upload first; for Threads see [threads-publish.md](./resources/threads-publish.md) |\n| “Image” in chat, no file | Stop; get file path or `https://` URL for `upload-from-url` |\n| Empty upload / `Content-Length: 0` | Re-upload a non-empty asset |\n| Unknown `integrations:trigger` | Method must appear in `output.tools` |\n| `--settings` parse error | Single-quoted JSON: `'{\"post_type\":\"post\"}'` |\n| Thread timing wrong | `-d` is **milliseconds**, not minutes |\n| Unknown global plug `func` | Run `plugs:catalog` and use `methodName` (e.g. `autoPlugPost`, `autoRepostPost`) |\n| Analytics rejected | `-d` must be **7**, **30**, or **90** |\n| Env key ignored | `auth:logout` if disk credentials exist |\n| Old CLI / wrong verify host | Compare `openquok --version` with the current release on the [CLI package page](https://www.npmjs.com/package/@openquok/auto-cli); reinstall or upgrade the binary there — skill install does not update it |\n\nFile v1.0.8:_meta.json\n\n{\n  \"ownerId\": \"kn7bz73j78bvq5mfqy2c9msscs896h8e\",\n  \"slug\": \"openquok-core\",\n  \"version\": \"1.0.8\",\n  \"publishedAt\": 1789446111518\n}\n\nFile v1.0.8:resources/command-reference.md\n\n# OpenQuok CLI — command reference\n\nAgent-oriented reference for `@openquok/auto-cli` (`openquok`). Hard rules, auth, and workflows live in [SKILL.md](../SKILL.md).\n\n## Environment variables\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `OPENQUOK_API_KEY` | No* | — | Bearer `opo_` programmatic access token |\n| `OPENQUOK_API_URL` | No | `https://api.openquok.com` | API base (`{OPENQUOK_API_URL}/api/v1/...`) |\n| `OPENQUOK_AUTH_SERVER` | No | `https://cli-auth.openquok.com` | OAuth2 device-flow server (`/device/*`, `/health`) |\n\n\\*Either `OPENQUOK_API_KEY` or stored credentials from `openquok auth:login` is required. **Stored credentials take priority** over the env var until `auth:logout`.\n\n## Config\n\n```bash\nopenquok config:show\n```\n\nPrints resolved `api_url`, `auth_server_url`, deployment mode (`openquok_cloud` vs `custom`), and value sources — no secrets.\n\n## Authentication\n\n```bash\n# Messaging agents (Telegram/Hermes) — two steps; do not use auth:login --json alone\nopenquok auth:login --json --no-poll\nopenquok auth:login:poll --device-code \"<device_code from stdout>\"\n\n# CI / long-running shell — single process may use auth:login --json (polls until done)\nopenquok auth:login --json\n\nopenquok auth:login --apiKey \"opo_…\"   # fallback when device flow cannot complete\nopenquok auth:status\nopenquok auth:workspace             # { workspace: { id, name } } for current credentials\nopenquok auth:logout\n```\n\n- **Preference:** device OAuth before a programmatic token when the user can open a browser link.\n- **Messaging hosts:** `--json --no-poll` then `auth:login:poll` after the user authorizes — otherwise credentials are never stored.\n- **Agents:** forward `verification_uri_complete` from stdout only — never fabricate codes or URLs.\n- **Humans with TTY:** `openquok auth:login` without `--json` is fine locally.\n- **Session start:** see Rule 0 in [SKILL.md](../SKILL.md) — run version + `auth:status` (+ `auth:workspace` when connected) via shell before the first assistant message; greet as the OpenQuok bot, not the host persona.\n- **Invalid or expired code:** Re-run `auth:login --json --no-poll` and `auth:login:poll` with a fresh `device_code` (~30 min).\n\n\n## Integrations\n\n```bash\n# List all connected social channels (integration UUIDs)\nopenquok integrations:list\n\n# List integrations belonging to a specific channel group (customer)\nopenquok integrations:list --group <customer-group-id>\n\n# List all channel groups (customers) as {id, name}\nopenquok integrations:groups\n\n# Get posting rules, character limits, and settings schema for an integration\nopenquok integrations:settings <integration-uuid>\n\n# Trigger an allow-listed provider method to fetch dynamic data\nopenquok integrations:trigger <integration-uuid> <method-name> [--data '<json>' | -d '<json>']\n```\n\n- `integrations:groups` — channel groups (`integration_customers`); pass an `id` to `integrations:list --group`.\n- `integrations:settings` — rules, `maxLength`, settings schema, allow-listed `tools` (`methodName`, `dataSchema`). Publish-time keys per channel: [provider-settings.md](./provider-settings.md).\n- `integrations:trigger` — single allow-listed method; `--data` must be a JSON object when required. Live examples: Dev.to `tags` / `organizations`; LinkedIn `company` (URL in `--data`).\n- New channels are connected in the web app (OAuth, or a dashboard API key for Dev.to); the CLI uses integration UUIDs from `integrations:list`.\n\n## Posts\n\n```bash\n# List posts (default ±30 local calendar days from today)\nopenquok posts:list\nopenquok posts:list --start \"2026-01-01T00:00:00Z\" --end \"2026-02-01T00:00:00Z\"\n\n# Create or schedule posts (-s / scheduledAt is REQUIRED unless using --json)\nopenquok posts:create -c \"…\" -s \"2026-01-01T12:00:00Z\" -i \"<uuid>\"\nopenquok posts:create -c \"…\" -s \"…\" -t draft -i \"<uuid>\"\nopenquok posts:create -c \"…\" -s \"…\" -i \"<uuid>\" -m '<[{id,path}]>'\nopenquok posts:create -c \"main\" -c \"reply\" -s \"…\" -d 5000 -i \"<uuid>\"\nopenquok posts:create --json ./post.json\n\n# Manage post rows\nopenquok posts:status <post-id> --status draft\nopenquok posts:status <post-id> -s schedule\nopenquok posts:reschedule <post-id> -s \"2026-06-15T14:30:00.000Z\"\nopenquok posts:reschedule <post-id> -s \"2026-06-20T10:00:00.000Z\" --action schedule --republish\nopenquok posts:review-todo <post-id> --note \"…\"\nopenquok posts:delete <post-id>\n\n# Resolve missing release_id before per-post analytics\nopenquok posts:missing <post-id>\nopenquok posts:connect <post-id> --release-id \"<provider-release-id>\"\n```\n\n### `posts:list`\n\n- Default window: ±30 **local calendar** days from today (ISO on the wire).\n- Override: `--start` / `--end` (aliases `--startDate` / `--endDate`).\n- Filter: `-i` / `--integrations` / `--integrationIds` (CSV), `--customer` / `--customerGroupId`.\n\n### `posts:status`\n\n- Takes a **post row** id from `posts:list` (same as `posts:delete`).\n- Flips `draft` ↔ `scheduled` at the stored publish time.\n\n### `posts:reschedule`\n\n- Takes a **post row** id from `posts:list` (any row in the group).\n- Required `-s` / `--scheduledAt` — new publish time (ISO-8601); same field as `POST /public/posts`.\n- `--action update` (default) — moves `publishDate` only; preserves each row's state (draft, scheduled, or published).\n- `--action schedule` — re-queues publishing at the new time and clears `releaseId`, `releaseUrl`, and errors.\n- `--republish` — required when `--action schedule` and the group already has published rows; otherwise the API returns `400`.\n- Use `posts:status` when you only need to flip draft ↔ scheduled at the **same** stored time — not to move the slot.\n\n### `posts:missing` / `posts:connect`\n\n- Use when `release_id` is `\"missing\"`: list provider candidates, then link with `--release-id` (aliases `--releaseId`, `-r`) for per-post analytics.\n\n### Media flags (`-m` / `--media`)\n\n- Value must be a JSON array of `{ \"id\", \"path\" }` from `openquok upload` or `openquok upload-from-url` (see Rule 2 in SKILL.md).\n- **Thread-style posts:** repeated `-c` for segments; optional repeated `-m` pairs with leading segments. `-d` is **milliseconds** between segments (default 5000).\n\n### `--json` / `-j`\n\n- Full `POST /public/posts` payload: `scheduledAt`, `status`, `bodiesByIntegrationId`, `providerSettingsByIntegrationId`, `media`, tags, etc.\n\n## Analytics\n\n```bash\n# Platform-level metrics for a connected channel (7, 30, or 90 days)\nopenquok analytics:platform <integration-uuid> [--days 7|30|90]\n\n# Per-post metrics for a published post row\nopenquok analytics:post <post-id> [--days 7|30|90]\n```\n\n- `--days` / `-d` must be **7**, **30**, or **90** (default 7).\n- `analytics:post` returns `[]` for drafts/queued rows.\n\n## Plugs\n\n| Type | CLI support | How |\n| --- | --- | --- |\n| **Internal plugs** | Yes | Per-post `providerSettingsByIntegrationId` on `posts:create` — `threads.internalEngagementPlug`, `*.crossAccountPlugs` |\n| **Global plugs** | Yes | `plugs:catalog`, `plugs:list <integration-id>`, `plugs:upsert`, `plugs:activate`, `plugs:delete` |\n\n```bash\nopenquok plugs:catalog\nopenquok plugs:list <integration-id>\nopenquok plugs:upsert <integration-id> --func autoPlugPost \\\n  --fields '[{\"name\":\"likesAmount\",\"value\":\"100\"},{\"name\":\"post\",\"value\":\"Thanks!\"}]'\nopenquok plugs:activate <plug-id> --activated true\nopenquok plugs:delete <plug-id>\n```\n\nChannels with plugs: Threads, X, LinkedIn, LinkedIn Page. Full catalog: [plugs.md](./plugs.md).\n\n## Media upload\n\n```bash\n# Upload a local file; returns media id and path for posts:create\nopenquok upload ./image.png\n\n# Upload from a remote URL; returns media id and path\nopenquok upload-from-url \"https://cdn.example.com/banner.png\"\n```\n\nBoth return `data.id` and `data.filePath` for use in `-m` / JSON `media` (`path` is the post field). `openquok upload` switches to direct-to-storage multipart for files over ~4 MB so hosted Cloud does not return HTTP 413.\n\n## Help\n\n```bash\nopenquok --help\nopenquok posts:create --help\n```\n\nFile v1.0.8:resources/devto-examples.md\n\n# Dev.to (`devto`) — CLI examples\n\n```bash\nDEVTO_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"devto\") | .id')\nopenquok integrations:settings \"$DEVTO_ID\"\n```\n\nConnect the channel in the OpenQuok dashboard with a personal API key (DEV Settings → Extensions). There is no public OAuth start URL.\n\nRun `integrations:settings` for `output.rules`, `output.maxLength`, typed `settingsSchema`, and allow-listed `output.tools` (`tags`, `organizations`).\n\nSettings mechanics: [provider-settings.md](./provider-settings.md). JSON recipes: [examples/EXAMPLES.md](./examples/EXAMPLES.md#devto).\n\n## Supported features\n\n| Feature | Supported | Notes |\n| --- | --- | --- |\n| Markdown article body | Yes | Root `-c` caption (up to 100,000 characters) |\n| Title | Yes | Required; min 2 characters (`title`) |\n| Tags | Yes | Up to 4 names; strings or `{ value, label }` |\n| Cover image | Yes | `main_image` / `mainImage` `{ path }` from a prior `upload` |\n| Canonical URL | Yes | `canonical` (aliases `canonical_url`, `canonicalUrl`) |\n| Organization | Yes | Numeric id from `integrations:trigger … organizations` |\n| Series | Yes | Free-text `series`; Dev.to creates the series if missing |\n| Tag / org lookup | Yes | `integrations:trigger` `tags` and `organizations` |\n| Channel / article analytics | Yes | `analytics:platform` and `analytics:post` — page views, reactions, comments |\n| Follow-up comments | No | Out of scope |\n| Public OAuth connect | No | Dashboard API key only |\n\n## Agent tasks\n\n| User wants to… | JSON example |\n| --- | --- |\n| Schedule a markdown article with title and tags | [devto-article-title-tags.json](./examples/devto-article-title-tags.json) |\n| Add the article to a series | [devto-series.json](./examples/devto-series.json) |\n| Syndicate with a canonical URL | [devto-canonical.json](./examples/devto-canonical.json) |\n| Publish under an organization with a cover | [devto-organization.json](./examples/devto-organization.json) |\n| List tag suggestions | `openquok integrations:trigger \"$DEVTO_ID\" tags` |\n| List organizations the key can publish under | `openquok integrations:trigger \"$DEVTO_ID\" organizations` |\n| See the typed settings schema | `openquok integrations:settings \"$DEVTO_ID\"` |\n| Track account performance | [Discover integration](#discover-integration) → `analytics:platform` |\n| Inspect a published article | [Post insights](#post-insights) |\n\n## Provider settings\n\nFlat JSON on `--settings` or inside `--providerSettingsByIntegrationId` for the Dev.to UUID. Nested `devto.*` matches the web composer bucket.\n\n| Key | Values | When |\n| --- | --- | --- |\n| `title` | string (min 2 chars) | Required for valid publish |\n| `tags` | strings or `[{ \"value\": \"…\", \"label\": \"…\" }]` | Optional; max 4 |\n| `canonical` | URL string | Optional syndication URL |\n| `canonical_url` / `canonicalUrl` | URL string | Aliases for `canonical` |\n| `organization` | integer id | Optional; from `organizations` tool |\n| `organization_id` / `organizationId` | integer | Aliases for `organization` |\n| `series` | string | Optional series name; creates the series if missing |\n| `main_image` / `mainImage` | `{ \"path\": \"…\" }` or path string | Optional cover after upload |\n| `devto.title` | string | Same as `title` (composer bucket) |\n| `devto.tags` | tag array | Same as `tags` |\n| `devto.canonical` | URL string | Same as `canonical` |\n| `devto.organization` | integer | Same as `organization` |\n| `devto.series` | string | Same as `series` |\n| `devto.mainImage` | `{ \"path\": \"…\" }` | Same as `mainImage` |\n\n**Rules:** Title min 2 characters. At most 4 tags. Body is markdown. Cover path must come from `openquok upload` / `upload-from-url` (Rule 2), not a raw local path. Duplicate canonical URLs fail at publish with a clear error.\n\n## Run an example\n\n```bash\nopenquok posts:create --json ./examples/devto-article-title-tags.json\nopenquok posts:create --json ./examples/devto-series.json\n```\n\n## Discover integration\n\n```bash\nopenquok integrations:settings \"$DEVTO_ID\"\nopenquok integrations:trigger \"$DEVTO_ID\" tags\nopenquok integrations:trigger \"$DEVTO_ID\" organizations\nopenquok analytics:platform \"$DEVTO_ID\" -d 30\n```\n\nPlatform analytics return daily page views, reactions, and comments for the connected Dev.to account (`-d 7` \\| `30` \\| `90`).\n\n## Post insights\n\n```bash\nPOST_ID=$(openquok posts:list | jq -r '.items[] | select(.identifier==\"devto\") | .id' | head -1)\nopenquok analytics:post \"$POST_ID\" -d 7\n```\n\nPer-post analytics use the same metric labels for a **published** article (linked Forem article id). Drafts and queued rows return `[]`.\n\nFile v1.0.8:resources/examples/EXAMPLES.md\n\n# OpenQuok CLI — JSON post examples\n\nCopy-paste payloads for `openquok posts:create --json ./examples/<file>.json`. Each file uses the **POST /public/posts** shape (`scheduledAt`, `status`, `body`, `integrationIds`, optional `media`, `providerSettingsByIntegrationId`, …).\n\n## Before you post\n\n1. Replace `<integration-id>` with a UUID from `openquok integrations:list`.\n2. Replace `<media-id>`, `<reply-media-id>`, and `https://cdn.example.com/…` paths with `{id, path}` from `openquok upload` or `openquok upload-from-url` (Rule 2 in [SKILL.md](../../SKILL.md)). Follow-up reply images use the same `media` shape on `replies[]` rows — upload each file before `posts:create`.\n3. Run `openquok integrations:settings <integration-id>` for `maxLength`, `rules`, and allow-listed `integrations:trigger` methods.\n\nGlobal plugs (likes-threshold channel rules) are configured with `plugs:*` commands — see [plugs.md](../plugs.md).\n\n```bash\nopenquok posts:create --json ./examples/threads-text-only.json\n```\n\n## Threads\n\n| File | Scenario |\n| --- | --- |\n| [threads-text-only.json](./threads-text-only.json) | Text-only scheduled post |\n| [threads-with-image.json](./threads-with-image.json) | Single image |\n| [threads-media-carousel.json](./threads-media-carousel.json) | Multi-image carousel |\n| [threads-follow-up-replies.json](./threads-follow-up-replies.json) | `threads.replies` chain (text only) |\n| [threads-follow-up-reply-with-image.json](./threads-follow-up-reply-with-image.json) | `threads.replies` with image on a reply row |\n| [threads-thread-finisher.json](./threads-thread-finisher.json) | Finisher + follow-ups |\n| [threads-engagement-plug.json](./threads-engagement-plug.json) | Internal plug — `threads.internalEngagementPlug` (same-account delayed reply) |\n| [threads-cross-account-plug.json](./threads-cross-account-plug.json) | Internal plug — `threads.crossAccountPlugs` (comment from other Threads channels) |\n\n## Facebook Page\n\n| File | Scenario |\n| --- | --- |\n| [facebook-text-only.json](./facebook-text-only.json) | Text feed post |\n| [facebook-with-image.json](./facebook-with-image.json) | Single photo |\n| [facebook-link-preview.json](./facebook-link-preview.json) | Link preview (`url`) |\n| [facebook-reel.json](./facebook-reel.json) | Reel from MP4 |\n| [facebook-story.json](./facebook-story.json) | Story (`post_type: story`) |\n| [facebook-multi-photo.json](./facebook-multi-photo.json) | Multi-photo carousel |\n| [facebook-follow-up-comment.json](./facebook-follow-up-comment.json) | Follow-up comments via `replies` (text only) |\n| [facebook-follow-up-comment-with-image.json](./facebook-follow-up-comment-with-image.json) | Follow-up comment with one image on `facebook.replies[]` |\n\n## Instagram\n\nShared recipes — use the same JSON with `instagram-standalone` or `instagram-business` integration UUIDs.\n\n| File | Scenario |\n| --- | --- |\n| [instagram-feed-post.json](./instagram-feed-post.json) | Feed image |\n| [instagram-carousel.json](./instagram-carousel.json) | Multi-image carousel |\n| [instagram-reel.json](./instagram-reel.json) | Reel (MP4) |\n| [instagram-story.json](./instagram-story.json) | Story |\n| [instagram-trial-reel.json](./instagram-trial-reel.json) | Trial Reel + collaborators |\n| [instagram-follow-up-comments.json](./instagram-follow-up-comments.json) | Text follow-ups via `instagram.replies` |\n\n## YouTube\n\n| File | Scenario |\n| --- | --- |\n| [youtube-video-title-privacy.json](./youtube-video-title-privacy.json) | Video + title + privacy |\n| [youtube-with-tags.json](./youtube-with-tags.json) | Nested `youtube.*` + tags |\n| [youtube-with-thumbnail.json](./youtube-with-thumbnail.json) | Custom thumbnail |\n| [youtube-flat-settings.json](./youtube-flat-settings.json) | Flat `--settings`-style keys |\n\n## TikTok\n\n| File | Scenario |\n| --- | --- |\n| [tiktok-video-direct-post.json](./tiktok-video-direct-post.json) | Direct publish + privacy |\n| [tiktok-photo-carousel.json](./tiktok-photo-carousel.json) | Photo carousel + title |\n| [tiktok-upload-inbox.json](./tiktok-upload-inbox.json) | Creator inbox (`UPLOAD`) |\n| [tiktok-private-draft.json](./tiktok-private-draft.json) | Private draft (`SELF_ONLY`) |\n\n## LinkedIn\n\n| File | Scenario |\n| --- | --- |\n| [linkedin-text-post.json](./linkedin-text-post.json) | Personal profile text |\n| [linkedin-document-carousel.json](./linkedin-document-carousel.json) | Image → PDF document carousel (`post_as_images_carousel`, `carousel_name`) |\n| [linkedin-with-video.json](./linkedin-with-video.json) | Single MP4 video |\n| [linkedin-follow-up-comment.json](./linkedin-follow-up-comment.json) | Text follow-up comments |\n| [linkedin-page-document-carousel.json](./linkedin-page-document-carousel.json) | Page document carousel (`linkedin.postAsImagesCarousel`) |\n\n## X\n\n| File | Scenario |\n| --- | --- |\n| [x-follow-up-replies.json](./x-follow-up-replies.json) | Quote-less reply chain via `x.replies` (text only) |\n| [x-follow-up-reply-with-image.json](./x-follow-up-reply-with-image.json) | Follow-up reply with image on `x.replies[]` |\n| [x-cross-account-repost.json](./x-cross-account-repost.json) | Internal plug — `x.crossAccountPlugs` (repost from other X channels) |\n\n## Dev.to\n\n| File | Scenario |\n| --- | --- |\n| [devto-article-title-tags.json](./devto-article-title-tags.json) | Markdown article + title + tags |\n| [devto-series.json](./devto-series.json) | Free-text series name |\n| [devto-canonical.json](./devto-canonical.json) | Canonical URL syndication |\n| [devto-organization.json](./devto-organization.json) | Organization id + cover `mainImage.path` |\n\n## Multi-channel\n\n| File | Scenario |\n| --- | --- |\n| [multi-platform-campaign.json](./multi-platform-campaign.json) | Per-channel bodies + settings |\n\nPer-channel feature matrices and CLI flags: `../{identifier}-examples.md`, [provider-settings.md](../provider-settings.md), and [plugs.md](../plugs.md).\n\nFile v1.0.8:resources/facebook-examples.md\n\n# Facebook Page — CLI examples\n\n```bash\nFB_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"facebook\") | .id')\nopenquok integrations:settings \"$FB_ID\"\n```\n\nRun `integrations:settings` for `output.rules`, `output.maxLength`, and allow-listed `output.tools`. Publish keys below are stable for the Facebook Page provider.\n\nSettings mechanics: [provider-settings.md](./provider-settings.md). JSON recipes: [examples/EXAMPLES.md](./examples/EXAMPLES.md#facebook-page).\n\n## Supported features\n\n| Feature | Supported | Notes |\n| --- | --- | --- |\n| Text feed post | Yes | `-c` only |\n| Link preview | Yes | Optional `url` in settings; **ignored when photos or video are attached** |\n| Single photo | Yes | One uploaded image via `-m` |\n| Multi-photo carousel | Yes | Multiple `-m` attachments in one post |\n| Reel (MP4 video) | Yes | Single `.mp4` → Page video API; Facebook surfaces eligible uploads as Reels |\n| Facebook Stories | Yes | `post_type: story` or `facebook.postType: story`; image or MP4 required; each attachment → its own Story |\n| Follow-up comments | Yes | `facebook.replies` — optional one image per reply (feed posts only; not Stories) |\n| Page analytics | Yes | `analytics:platform` and `analytics:post` |\n| Personal profile / Groups | No | Pages you manage via Graph API only |\n\n## Agent tasks\n\n| User wants to… | JSON example |\n| --- | --- |\n| Post text to the Page | [facebook-text-only.json](./examples/facebook-text-only.json) |\n| Share a link with preview card | [facebook-link-preview.json](./examples/facebook-link-preview.json) |\n| Post a photo | [facebook-with-image.json](./examples/facebook-with-image.json) |\n| Post multiple photos | [facebook-multi-photo.json](./examples/facebook-multi-photo.json) |\n| Publish a Reel from MP4 | [facebook-reel.json](./examples/facebook-reel.json) |\n| Publish a Story (image or MP4) | [facebook-story.json](./examples/facebook-story.json) |\n| Add a comment after the post goes live | [facebook-follow-up-comment.json](./examples/facebook-follow-up-comment.json) |\n| Add a comment with one image after publish | [facebook-follow-up-comment-with-image.json](./examples/facebook-follow-up-comment-with-image.json) |\n| See what the Page supports | `openquok integrations:settings \"$FB_ID\"` |\n| Track Page performance | [Discover integration](#discover-integration) → `analytics:platform` |\n\n## Provider settings\n\nFlat JSON on `--settings` or inside `--providerSettingsByIntegrationId` for the Page UUID.\n\n| Key | Values | When |\n| --- | --- | --- |\n| `post_type` / `postType` | `post` (default) or `story` | Feed/Reel vs Story surface |\n| `facebook.postType` | `post` or `story` | Same as `post_type` (web composer bucket; API accepts both) |\n| `url` | `https://…` string | Text-only post with link-preview card |\n| `facebook.url` | `https://…` | Same as `url` (web composer bucket; API accepts both) |\n| `facebook.replies` | `[{ \"id\": \"…\", \"message\": \"…\", \"delaySeconds\": 60, \"media\": [...] }]` | Follow-up comments after publish (feed posts only; nested bucket in JSON) |\n\n**Rules:** Link `url` applies only when **no** media is attached and post type is `post`. With `-m`, the post uses attached photos or video instead of a link card. **Stories** require at least one image or MP4; each attachment publishes as its own Story. Follow-up `replies` are not supported for Stories.\n\n### Follow-up comments (`facebook.replies`)\n\nSame-account comments on the main post use the **`facebook`** bucket — not `threads.replies`.\n\nEach reply row:\n\n```json\n{\n  \"id\": \"reply-1\",\n  \"message\": \"First comment on the post\",\n  \"delaySeconds\": 60,\n  \"media\": [{ \"id\": \"<media-id>\", \"path\": \"https://cdn.example.com/reply.jpg\" }]\n}\n```\n\n- `delaySeconds` — wait after the previous part publishes (`0` = immediately after the prior step).\n- `media` — optional. Max **one image** per reply; **no video**. Upload first (Rule 2) before referencing `id` / `path`. Omit `media` for text-only comments.\n\nText-only recipe: [facebook-follow-up-comment.json](./examples/facebook-follow-up-comment.json). With one image on a reply row: [facebook-follow-up-comment-with-image.json](./examples/facebook-follow-up-comment-with-image.json). Mechanics: [provider-settings.md](./provider-settings.md#scheduled-follow-up-replies).\n\n**Follow-up with one image** (upload first, then nest under `facebook.replies`):\n\n```bash\nREPLY_MEDIA=$(openquok upload ./comment-image.jpg | jq -c '[{id: .data.id, path: (.data.path // .data.filePath)}]')\n\nopenquok posts:create \\\n  -s \"2026-01-01T12:00:00Z\" \\\n  -c \"Main post\" \\\n  -i \"$FB_ID\" \\\n  --providerSettingsByIntegrationId \"$(jq -nc --arg id \"$FB_ID\" --argjson media \"$REPLY_MEDIA\" '\n    { ($id): { facebook: { replies: [\n      { id: \"reply-1\", message: \"See the chart in this comment\", delaySeconds: 60, media: $media }\n    ] } } }\n  ')\"\n```\n\n## Run an example\n\n```bash\nopenquok posts:create --json ./examples/facebook-link-preview.json\n```\n\nAt publish time the backend resolves each stored object key to a public `https://` URL for Meta to fetch.\n\n## Discover integration\n\n```bash\nopenquok integrations:settings \"$FB_ID\"\nopenquok analytics:platform \"$FB_ID\" -d 30\n```\n\n## Post insights\n\n```bash\nPOST_ID=$(openquok posts:list | jq -r '.items[0].id')\nopenquok analytics:post \"$POST_ID\" -d 7\n```\n\nFile v1.0.8:resources/instagram-business-examples.md\n\n# Instagram — business (`instagram-business`)\n\nProfessional Instagram account connected via **Facebook Login for Business** (Page-linked). Confirm keys with `integrations:settings` for your workspace row.\n\n```bash\nIG_BUSINESS_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"instagram-business\") | .id')\nopenquok integrations:settings \"$IG_BUSINESS_ID\"\n```\n\nPosting behavior matches **Instagram (Standalone)** — only OAuth and token host differ. See [instagram-standalone-examples.md](./instagram-standalone-examples.md) for the same recipes with `instagram-standalone`.\n\nSettings mechanics: [provider-settings.md](./provider-settings.md). JSON recipes: [examples/EXAMPLES.md](./examples/EXAMPLES.md#instagram).\n\n## Agent tasks\n\n| User wants to… | JSON example |\n| --- | --- |\n| Post a feed image | [instagram-feed-post.json](./examples/instagram-feed-post.json) |\n| Post a carousel | [instagram-carousel.json](./examples/instagram-carousel.json) |\n| Publish a Reel | [instagram-reel.json](./examples/instagram-reel.json) |\n| Publish a Story | [instagram-story.json](./examples/instagram-story.json) |\n| Test a Trial Reel with collaborators | [instagram-trial-reel.json](./examples/instagram-trial-reel.json) |\n| Add text comments after publish | [instagram-follow-up-comments.json](./examples/instagram-follow-up-comments.json) |\n| Check limits and tools | `openquok integrations:settings \"$IG_BUSINESS_ID\"` |\n\n## Supported features\n\n| Feature | Supported | Notes |\n| --- | --- | --- |\n| Feed image post | Yes | At least one attachment required for `scheduled` |\n| Carousel (2–10 items) | Yes | Auto when `-m` has multiple attachments and `post_type` is not `story` |\n| Reel (single video) | Yes | One `.mp4` attachment → Reels surface |\n| Story | Yes | `post_type: \"story\"`; one attachment; no collaborators |\n| Trial Reel | Yes | `is_trial_reel` + single MP4; not combinable with Stories |\n| Collaborators (max 3) | Yes | Feed/Reel **single** media only — not carousel, not Stories |\n| Graduation strategy | Yes | `MANUAL` or `SS_PERFORMANCE` when `is_trial_reel` is true |\n| Text follow-up comments | Yes | `instagram.replies` in provider settings |\n| Story link stickers | No | — |\n| Automatic comment auto-reply | No | — |\n\n## Provider settings (`--settings`)\n\nFlat JSON merged into `providerSettingsByIntegrationId` for each `-i` UUID. Run `integrations:settings` to confirm allow-listed keys in your workspace.\n\n| Key | Values | Default | When |\n| --- | --- | --- | --- |\n| `post_type` | `\"post\"` \\| `\"story\"` | `\"post\"` | Story vs feed/Reel |\n| `is_trial_reel` | `true` \\| `false` | `false` | Trial Reel (feed only, one video) |\n| `graduation_strategy` | `\"MANUAL\"` \\| `\"SS_PERFORMANCE\"` | `\"MANUAL\"` | Trial Reel graduation |\n| `collaborators` | `[\"user1\",\"user2\"]` or `[{\"label\":\"user1\"}]` | `[]` | Max 3; not with carousel or Stories |\n| `instagram.replies` | `[{ \"id\": \"…\", \"message\": \"…\", \"delaySeconds\": 60 }]` | `[]` | Scheduled text comments (nested bucket in JSON) |\n\n## Run an example\n\nUse the same JSON files with an `instagram-business` integration UUID:\n\n```bash\nopenquok posts:create --json ./examples/instagram-feed-post.json\n```\n\nFile v1.0.8:resources/instagram-standalone-examples.md\n\n# Instagram — standalone (`instagram-standalone`)\n\nProfessional Instagram account connected via **Instagram Login** (no Facebook Page required).\n\n```bash\nIG_STANDALONE_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"instagram-standalone\") | .id')\nopenquok integrations:settings \"$IG_STANDALONE_ID\"\n```\n\nAlways run `integrations:settings` for required fields and allow-listed `output.tools` before posting. Posting behavior matches **Instagram (Business)** — see [instagram-business-examples.md](./instagram-business-examples.md) for the same feature matrix with `instagram-business`.\n\nSettings mechanics: [provider-settings.md](./provider-settings.md). JSON recipes: [examples/EXAMPLES.md](./examples/EXAMPLES.md#instagram).\n\n## Agent tasks\n\n| User wants to… | JSON example |\n| --- | --- |\n| Post a feed image | [instagram-feed-post.json](./examples/instagram-feed-post.json) |\n| Post a carousel | [instagram-carousel.json](./examples/instagram-carousel.json) |\n| Publish a Reel | [instagram-reel.json](./examples/instagram-reel.json) |\n| Publish a Story | [instagram-story.json](./examples/instagram-story.json) |\n| Test a Trial Reel with collaborators | [instagram-trial-reel.json](./examples/instagram-trial-reel.json) |\n| Add text comments after publish | [instagram-follow-up-comments.json](./examples/instagram-follow-up-comments.json) |\n| Check limits and tools | `openquok integrations:settings \"$IG_STANDALONE_ID\"` |\n\n## Supported features\n\n| Feature | Supported | Notes |\n| --- | --- | --- |\n| Feed image post | Yes | At least one attachment required for `scheduled` |\n| Carousel (2–10 items) | Yes | Auto when `-m` has multiple attachments and `post_type` is not `story` |\n| Reel (single video) | Yes | One `.mp4` attachment → Reels surface |\n| Story | Yes | `post_type: \"story\"`; one attachment; no collaborators |\n| Trial Reel | Yes | `is_trial_reel` + single MP4; not combinable with Stories |\n| Collaborators (max 3) | Yes | Feed/Reel **single** media only — not carousel, not Stories |\n| Graduation strategy | Yes | `MANUAL` or `SS_PERFORMANCE` when `is_trial_reel` is true |\n| Text follow-up comments | Yes | `instagram.replies` in provider settings |\n| Story link stickers | No | — |\n| Automatic comment auto-reply | No | — |\n\n## Provider settings (`--settings`)\n\nFlat JSON merged into `providerSettingsByIntegrationId` for each `-i` UUID.\n\n| Key | Values | Default | When |\n| --- | --- | --- | --- |\n| `post_type` | `\"post\"` \\| `\"story\"` | `\"post\"` | Story vs feed/Reel |\n| `is_trial_reel` | `true` \\| `false` | `false` | Trial Reel (feed only, one video) |\n| `graduation_strategy` | `\"MANUAL\"` \\| `\"SS_PERFORMANCE\"` | `\"MANUAL\"` | Trial Reel graduation |\n| `collaborators` | `[\"user1\",\"user2\"]` or `[{\"label\":\"user1\"}]` | `[]` | Max 3; not with carousel or Stories |\n| `instagram.replies` | `[{ \"id\": \"…\", \"message\": \"…\", \"delaySeconds\": 60 }]` | `[]` | Scheduled text comments (nested bucket in JSON) |\n\n## Run an example\n\nUse the same JSON files with an `instagram-standalone` integration UUID:\n\n```bash\nopenquok posts:create --json ./examples/instagram-feed-post.json\n```\n\nFile v1.0.8:resources/linkedin-examples.md\n\n# LinkedIn (`linkedin`)\n\nPersonal professional profile channel. Single-step OAuth.\n\nJSON recipes: [examples/EXAMPLES.md](./examples/EXAMPLES.md#linkedin). Settings mechanics: [provider-settings.md](./provider-settings.md).\n\n## Supported features\n\n| Feature | Supported |\n| --- | --- |\n| Text posts (3,000 chars) | Yes |\n| Single / multi-image | Yes |\n| MP4 video (one attachment) | Yes |\n| Image → PDF document carousel | Yes (≥2 images, no video) |\n| Follow-up text comments | Yes — `linkedin.replies`; text only (no media on follow-ups) |\n| Cross-account comment / reshare (internal plugs) | Yes (`linkedin.crossAccountPlugs`) |\n| Account / post analytics | No (Page only) |\n\n## Agent tasks\n\n| User intent | JSON example |\n| --- | --- |\n| Connect personal LinkedIn | Setup in human docs; identifier `linkedin` |\n| Schedule a text post | [linkedin-text-post.json](./examples/linkedin-text-post.json) |\n| Post with video | [linkedin-with-video.json](./examples/linkedin-with-video.json) |\n| Image → PDF document carousel | [linkedin-document-carousel.json](./examples/linkedin-document-carousel.json) |\n| Add a comment after publish | [linkedin-follow-up-comment.json](./examples/linkedin-follow-up-comment.json) |\n| Comment or reshare from other LinkedIn channels (internal plug) | `linkedin.crossAccountPlugs` — see [plugs.md](./plugs.md) |\n\nFor Page document carousels and analytics, use `linkedin-page` — see [linkedin-page-examples.md](./linkedin-page-examples.md).\n\n## Provider settings\n\n| Key (flat CLI) | Nested web bucket | Purpose |\n| --- | --- | --- |\n| `post_as_images_carousel` | `linkedin.postAsImagesCarousel` | Convert ≥2 images to PDF document (no video) |\n| `carousel_name` | `linkedin.carouselName` | PDF title (default `slides`) |\n| `linkedin.replies` | `linkedin.replies` | Text follow-up comments after publish (no `media` on reply rows) |\n| `linkedin.crossAccountPlugs` | `linkedin.crossAccountPlugs` | Cross-account comment (`linkedin-add-comment`) or reshare (`linkedin-repost-post-users`) |\n\nFlat keys work on `--settings` or inside `--providerSettingsByIntegrationId`. Prefer the nested `linkedin.*` bucket in JSON files (matches composer).\n\n### Follow-up comments (`linkedin.replies`)\n\nSame-account comments on the main post live under the **`linkedin`** bucket — including **`linkedin-page`** integrations (alias bucket, not `threads.replies`).\n\nEach reply row:\n\n```json\n{ \"id\": \"reply-1\", \"message\": \"Follow-up comment on the post\", \"delaySeconds\": 60 }\n```\n\n- `delaySeconds` — wait after the previous part publishes (`0` = immediately after the prior step).\n- **No `media`** — put images and video on the main post only. LinkedIn follow-ups are text-only in the composer and at publish time.\n\nCopy-paste recipe: [linkedin-follow-up-comment.json](./examples/linkedin-follow-up-comment.json). Mechanics: [provider-settings.md](./provider-settings.md#scheduled-follow-up-replies).\n\nCross-account shape: [provider-settings.md](./provider-settings.md#internal-plugs). Plug catalog: [plugs.md](./plugs.md).\n\n## Run an example\n\nReplace `<integration-id>` and media paths with values from `openquok integrations:list` and `openquok upload`.\n\n```bash\nopenquok integrations:list --provider linkedin\nopenquok posts:create --json ./examples/linkedin-document-carousel.json\n```\n\nFlat CLI equivalent for document carousel:\n\n```bash\nopenquok posts:create \\\n  -i \"<integration-id>\" \\\n  -c \"Swipe through our latest slides.\" \\\n  -s \"2026-06-22T10:00:00.000Z\" \\\n  --settings '{\"post_as_images_carousel\":true,\"carousel_name\":\"June deck\"}' \\\n  -m '[{\"id\":\"<media-id-1>\",\"path\":\"https://cdn.example.com/slide-1.jpg\"},{\"id\":\"<media-id-2>\",\"path\":\"https://cdn.example.com/slide-2.jpg\"}]'\n```\n\nFile v1.0.8:resources/linkedin-page-examples.md\n\n# LinkedIn Page (`linkedin-page`)\n\nCompany Page channel. Two-step OAuth (login, then Page picker).\n\nJSON recipes: [examples/EXAMPLES.md](./examples/EXAMPLES.md#linkedin). Settings mechanics: [provider-settings.md](./provider-settings.md).\n\n## Supported features\n\n| Feature | Supported |\n| --- | --- |\n| Text posts (3,000 chars) | Yes |\n| Single / multi-image | Yes |\n| MP4 video (one attachment) | Yes |\n| Image → PDF document carousel | Yes (≥2 images, no video) |\n| Follow-up text comments | Yes |\n| Cross-account comment / reshare (internal plugs) | Yes (`linkedin.crossAccountPlugs`) |\n| Global plugs (likes threshold) | Yes — `plugs:*` CLI or web **Account → Plugs** |\n| Account analytics | Yes |\n| Per-post analytics | Yes |\n\n## Agent tasks\n\n| User intent | JSON example |\n| --- | --- |\n| Connect a company Page | OAuth `linkedin-page` + Page picker |\n| Schedule slide deck / carousel | [linkedin-page-document-carousel.json](./examples/linkedin-page-document-carousel.json) |\n| Pull Page insights | `analytics:platform` (see below) |\n| Set global plug rules (auto repost / comment at likes threshold) | `plugs:upsert` — see [plugs.md](./plugs.md) |\n\n## Provider settings\n\n| Key (flat CLI) | Nested web bucket | Purpose |\n| --- | --- | --- |\n| `post_as_images_carousel` | `linkedin.postAsImagesCarousel` | Convert images to PDF document |\n| `carousel_name` | `linkedin.carouselName` | PDF title (default `slides`) |\n| `linkedin.crossAccountPlugs` | `linkedin.crossAccountPlugs` | Cross-account comment or reshare — see [plugs.md](./plugs.md) |\n\n## Run an example\n\n```bash\nopenquok integrations:list --provider linkedin-page\nopenquok posts:create --json ./examples/linkedin-page-document-carousel.json\nopenquok analytics:platform -i \"<integration-id>\" -d 30\n```\n\nFlat CLI equivalent:\n\n```bash\nopenquok posts:create \\\n  -i \"<integration-id>\" \\\n  -c \"Our Q2 product slides — swipe through the deck.\" \\\n  -s \"2026-06-22T10:00:00.000Z\" \\\n  -j '{\"providerSettingsByIntegrationId\":{\"<integration-id>\":{\"linkedin\":{\"postAsImagesCarousel\":true,\"carouselName\":\"Q2 update\"}}}}'\n```\n\nFile v1.0.8:resources/patterns.md\n\n# Workflow recipes\n\nExtended `openquok` patterns. Rules and auth: [SKILL.md](../SKILL.md). Commands: [command-reference.md](./command-reference.md). Per-channel features and publish settings: [provider-settings.md](./provider-settings.md) and `*-examples.md`. Plugs (internal + global): [plugs.md](./plugs.md).\n\n## Resolve integration UUIDs\n\n```bash\nopenquok integrations:list | jq -r '.[] | {id, identifier}'\nopenquok integrations:settings <integration-uuid>\n```\n\nMeta channels today: `threads`, `facebook`, `instagram-standalone`, `instagram-business`. LinkedIn: `linkedin`, `linkedin-page`. Dev.to: `devto` (`tags`, `organizations`). Call `integrations:trigger` only for `methodName` values listed under `output.tools`.\n\n## Allow-listed provider tools\n\n```bash\nTH_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"threads\") | .id')\nopenquok integrations:settings \"$TH_ID\"\nopenquok integrations:trigger \"$TH_ID\" <method-from-settings> -d '{}'\n```\n\nReplace `<method-from-settings>` and `-d` using `output.tools[].methodName` and `dataSchema`. Dev.to examples:\n\n```bash\nDEVTO_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"devto\") | .id')\nopenquok integrations:trigger \"$DEVTO_ID\" tags\nopenquok integrations:trigger \"$DEVTO_ID\" organizations\n```\n\nLinkedIn `company` needs a URL payload:\n\n```bash\nLI_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"linkedin\") | .id')\nopenquok integrations:trigger \"$LI_ID\" company -d '{\"url\":\"https://www.linkedin.com/company/example\"}'\n```\n\n## Multiple attachments\n\n```bash\nMEDIA=$(jq -s 'add' \\\n  <(openquok upload ./a.jpg | jq '[{id: .data.id, path: (.data.path // .data.filePath)}]') \\\n  <(openquok upload ./b.jpg | jq '[{id: .data.id, path: (.data.path // .data.filePath)}]'))\nopenquok posts:create -c \"…\" -m \"$MEDIA\" -s \"2026-01-01T12:00:00Z\" -i \"<uuid>\"\n```\n\n## Multi-channel campaign (JSON file)\n\nUse [examples/multi-platform-campaign.json](./examples/multi-platform-campaign.json) — per-channel bodies and `providerSettingsByIntegrationId`.\n\n```bash\nopenquok posts:create --json ./examples/multi-platform-campaign.json\n```\n\n## Enforce max length\n\n```bash\nINTEGRATION_ID=\"<uuid>\"\nCONTENT=\"Your caption\"\nMAX=$(openquok integrations:settings \"$INTEGRATION_ID\" | jq '.output.maxLength')\n# Truncate CONTENT when ${#CONTENT} -gt MAX before posts:create\n```\n\n## Batch schedule\n\nLoop `openquok upload` + `posts:create` per slot; reuse one integration UUID; vary `-s` and `-c` per iteration.\n\n## Internal plugs on scheduled posts\n\nAttach internal plugs when creating posts — same-account Threads reply or cross-account comment/repost/reshare. Use `providerSettingsByIntegrationId` with the channel bucket (`threads`, `x`, `linkedin`). Examples: [threads-engagement-plug.json](./examples/threads-engagement-plug.json), [threads-cross-account-plug.json](./examples/threads-cross-account-plug.json), [x-cross-account-repost.json](./examples/x-cross-account-repost.json). Catalog: [plugs.md](./plugs.md).\n\n## Global plugs on channels\n\n```bash\nopenquok plugs:catalog\nopenquok plugs:list <integration-id>\nopenquok plugs:upsert <integration-id> --func autoPlugPost \\\n  --fields '[{\"name\":\"likesAmount\",\"value\":\"100\"},{\"name\":\"post\",\"value\":\"Grab the link in bio!\"}]'\n```\n\nSee [plugs.md](./plugs.md) for provider matrix and `plugs:activate` / `plugs:delete`.\n\n## Retry on transient failure\n\nRetry `posts:create` with exponential backoff (e.g. 2s, 4s, 8s) up to a fixed attempt cap; surface the last stderr/stdout to the user.\n\nFile v1.0.8:resources/plugs.md\n\n# Plugs — internal and global\n\nOpenQuok **plugs** automate engagement after a post goes live. They are included on all paid plans (see [pricing](https://www.openquok.com/pricing)).\n\n| Type | Scope | When it runs | Configure via CLI |\n| --- | --- | --- | --- |\n| **Internal plugs** | Per post (compose time) | After publish — same account or other connected channels in the workspace | Yes — `providerSettingsByIntegrationId` on `posts:create` |\n| **Global plugs** | Per channel (account rules) | When a published post crosses a likes threshold; checks every 6h, up to 3 runs | Yes — `plugs:catalog`, `plugs:list`, `plugs:upsert`, `plugs:activate`, `plugs:delete` |\n\nProvider support is plug-based only — not every channel has plugs. Facebook, Instagram, YouTube, and TikTok do **not** expose internal or global plugs today.\n\n---\n\n## Internal plugs\n\nBoost engagement from **the publishing channel** or **other connected channels in the same workspace** after the post is live.\n\n### Same-account (Threads only)\n\nSchedule an extra reply from the **same** Threads channel after follow-up replies and the thread finisher complete.\n\n| Provider bucket | Key | Example |\n| --- | --- | --- |\n| `threads` | `threads.internalEngagementPlug` | `{ \"enabled\": true, \"message\": \"…\", \"delaySeconds\": 300 }` |\n\nExample: [threads-engagement-plug.json](./examples/threads-engagement-plug.json).\n\n### Cross-account\n\nOther connected channels act on the post (comment, repost, reshare). Configure on the **publishing** integration’s provider bucket via `crossAccountPlugs`.\n\n| Provider bucket | Plug id | Action |\n| --- | --- | --- |\n| `threads` | `threads-cross-account-comment` | Comment from other Threads channels (`fields.comment`) |\n| `x` | `x-repost-post-users` | Repost from other X channels |\n| `linkedin` / `linkedin-page` | `linkedin-add-comment` | Comment from other LinkedIn channels (`fields.comment`) |\n| `linkedin` / `linkedin-page` | `linkedin-repost-post-users` | Reshare from other LinkedIn channels |\n\nEach `crossAccountPlugs` entry:\n\n```json\n{\n  \"plugName\": \"threads-cross-account-comment\",\n  \"enabled\": true,\n  \"delayMs\": 0,\n  \"integrationIds\": [\"<acting-integration-id>\"],\n  \"fields\": { \"comment\": \"Nice post!\" }\n}\n```\n\n- `delayMs` — milliseconds after publish (0 = immediately; composer offers 1h–24h presets).\n- `integrationIds` — UUIDs of **acting** channels from `openquok integrations:list` (must not include the publishing integration).\n- `fields` — plug-specific strings (`comment` for comment plugs; `{}` for repost/reshare plugs).\n\nExamples: [threads-cross-account-plug.json](./examples/threads-cross-account-plug.json), [x-cross-account-repost.json](./examples/x-cross-account-repost.json).\n\nFull key reference: [provider-settings.md](./provider-settings.md#internal-plugs).\n\n---\n\n## Global plugs\n\nChannel-level rules that fire when a **published** post reaches a **likes threshold** (e.g. 100 likes). The orchestrator re-checks every **6 hours**, up to **3 times** per post.\n\n| Channel | Rules available |\n| --- | --- |\n| Threads | Auto plug post — publish a reply when likes ≥ threshold |\n| X | Auto repost — repost when likes ≥ threshold; Auto plug post — reply when likes ≥ threshold |\n| LinkedIn Page | Auto repost — reshare when likes ≥ threshold; Auto plug post — comment when likes ≥ threshold |\n\nPersonal LinkedIn (`linkedin`) has internal plugs only — no global plug catalog.\n\n### CLI commands\n\n```bash\n# Discover plug types and field names for a provider\nopenquok plugs:catalog | jq '.plugs[] | select(.identifier==\"threads\")'\n\n# List saved rules on a channel\nopenquok plugs:list <integration-id>\n\n# Create a Threads auto-reply at 100 likes\nopenquok plugs:upsert <integration-id> \\\n  --func autoPlugPost \\\n  --fields '[{\"name\":\"likesAmount\",\"value\":\"100\"},{\"name\":\"post\",\"value\":\"Thanks for reading!\"}]'\n\n# Pause or resume a rule\nopenquok plugs:activate <plug-id> --activated false\n\n# Remove a rule\nopenquok plugs:delete <plug-id>\n```\n\nUse `methodName` from `plugs:catalog` as `--func`. Field names match the catalog `fields[].name` entries (`likesAmount`, `post`, …).\n\nThe web app **Account → Plugs** (`/account/plugs`) offers the same rules with a UI.\n\n---\n\n## Quick reference by channel\n\n| Channel | Internal plugs | Global plugs | Channel doc |\n| --- | --- | --- | --- |\n| Threads | Same-account reply, cross-account comment | Auto plug post | [threads-examples.md](./threads-examples.md) |\n| X | Cross-account repost | Auto repost, auto plug post | [x-examples.md](./x-examples.md) |\n| LinkedIn | Cross-account comment, cross-account reshare | — | [linkedin-examples.md](./linkedin-examples.md) |\n| LinkedIn Page | Cross-account comment, cross-account reshare | Auto repost, auto plug post | [linkedin-page-examples.md](./linkedin-page-examples.md) |\n\nArchive v1.0.7: 62 files, 60419 bytes\n\nFiles: resources/command-reference.md (7184b), resources/devto-examples.md (4618b), resources/examples/devto-article-title-tags.json (508b), resources/examples/devto-canonical.json (505b), resources/examples/devto-organization.json (515b), resources/examples/devto-series.json (413b), resources/examples/EXAMPLES.md (5902b), resources/examples/facebook-follow-up-comment-with-image.json (519b), resources/examples/facebook-follow-up-comment.json (363b), resources/examples/facebook-link-preview.json (269b), resources/examples/facebook-multi-photo.json (308b), resources/examples/facebook-reel.json (230b), resources/examples/facebook-story.json (314b), resources/examples/facebook-text-only.json (148b), resources/examples/facebook-with-image.json (222b), resources/examples/instagram-carousel.json (424b), resources/examples/instagram-feed-post.json (329b), resources/examples/instagram-follow-up-comments.json (529b), resources/examples/instagram-reel.json (218b), resources/examples/instagram-story.json (314b), resources/examples/instagram-trial-reel.json (465b), resources/examples/linkedin-document-carousel.json (587b), resources/examples/linkedin-follow-up-comment.json (367b), resources/examples/linkedin-page-document-carousel.json (527b), resources/examples/linkedin-text-post.json (138b), resources/examples/linkedin-with-video.json (243b), resources/examples/multi-platform-campaign.json (988b), resources/examples/threads-cross-account-plug.json (612b), resources/examples/threads-engagement-plug.json (436b), resources/examples/threads-follow-up-replies.json (476b), resources/examples/threads-follow-up-reply-with-image.json (533b), resources/examples/threads-media-carousel.json (301b), resources/examples/threads-text-only.json (140b), resources/examples/threads-thread-finisher.json (474b), resources/examples/threads-with-image.json (228b), resources/examples/tiktok-photo-carousel.json (527b), resources/examples/tiktok-private-draft.json (626b), resources/examples/tiktok-upload-inbox.json (460b), resources/examples/tiktok-video-direct-post.json (485b), resources/examples/x-cross-account-repost.json (501b), resources/examples/x-follow-up-replies.json (349b), resources/examples/x-follow-up-reply-with-image.json (494b), resources/examples/youtube-flat-settings.json (426b), resources/examples/youtube-video-title-privacy.json (444b), resources/examples/youtube-with-tags.json (579b), resources/examples/youtube-with-thumbnail.json (486b), resources/facebook-examples.md (5302b), resources/instagram-business-examples.md (3193b), resources/instagram-standalone-examples.md (3135b), resources/linkedin-examples.md (3720b), resources/linkedin-page-examples.md (2091b), resources/patterns.md (3515b), resources/plugs.md (4828b), resources/provider-settings.md (11803b), resources/threads-examples.md (6961b), resources/threads-publish.md (2586b), resources/tiktok-examples.md (7439b), resources/x-examples.md (6015b), resources/youtube-examples.md (3647b), skill-card.md (2790b), SKILL.md (15154b), _meta.json (132b)\n\nFile v1.0.7:SKILL.md\n\n---\nname: openquok-core\ndescription: >-\n  Schedule and manage social posts with the openquok CLI — authenticate, upload media, create drafts and scheduled posts, configure internal plugs, and read channel analytics for integrations in your OpenQuok workspace.\nhomepage: https://www.npmjs.com/package/@openquok/auto-cli\nversion: 1.0.0\nlicense: MIT\ncompatibility: Requires the global openquok CLI on PATH (see homepage). Installing this skill does not add the binary.\nprerequisites:\n  commands: [openquok]\nmetadata: {\"openclaw\":{\"emoji\":\"📮\",\"always\":true,\"requires\":{\"bins\":[\"openquok\"]},\"homepage\":\"https://www.npmjs.com/package/@openquok/auto-cli\"},\"hermes\":{\"tags\":[\"social-media\",\"openquok\",\"scheduling\"],\"category\":\"social-media\",\"requires_toolsets\":[\"terminal\"]},\"grok-bot\":{\"tags\":[\"social-media\",\"openquok\",\"scheduling\"],\"category\":\"social-media\",\"requires_toolsets\":[\"terminal\"],\"workspace_skill_path\":\"/workspace/openquok-core/SKILL.md\"},\"thinkrail\":{\"tags\":[\"social-media\",\"openquok\",\"scheduling\"],\"category\":\"social-media\",\"requires_toolsets\":[\"terminal\"],\"skill_paths\":[\"~/.pi/agent/skills/openquok-core/SKILL.md\",\".pi/skills/openquok-core/SKILL.md\"]}}\n---\n\n<!-- SPDX-FileCopyrightText: 2026 Rati Montreewat -->\n<!-- SPDX-License-Identifier: MIT -->\n\n## Session opening (first turn after reset)\n\n**When:** first assistant reply after `/new`, `/reset`, a new channel thread, or a “new session started” notice.\n\n**On that turn only:** use the OpenQuok bot voice below instead of a generic host welcome. Do **not** reuse this block on later turns.\n\n**One message only.** Run shell (below), then send **exactly one** assistant message. Forbidden on this turn:\n\n- A persona line before tools (e.g. “Hello, … I’m Atlas … What should we focus on?”).\n- A second message with only CLI version (e.g. “The OpenQuok CLI version is 0.0.6.”).\n- Repeating the host greeting after the system “new session started” line.\n\n**Shell (before any user-visible text):**\n\n```bash\nopenquok --version\nopenquok auth:status\n```\n\nIf `auth:status` shows `\"connected\": true`, also run `openquok auth:workspace`.\n\n**Required opening sentence (verbatim start):** `Hi, I am the OpenQuok bot.`\n\n**Same message must also include:**\n\n1. Installed CLI version from `openquok --version`.\n2. If the user may be on an old build: note that skill install does not upgrade the CLI and offer to walk through upgrade using the [CLI package page](https://www.npmjs.com/package/@openquok/auto-cli) — only after they agree.\n3. Auth: if connected, say you are authenticated and name **`workspace.name`**; if not, say not authenticated and offer the **two-step device flow** (below) or a programmatic token (`opo_`). **Never** run `auth:login --json` without `--no-poll` on messaging hosts — the shell exits before credentials are stored.\n\n**Fill-in template (one paragraph — replace `…` from shell output):**\n\n> Hi, I am the OpenQuok bot. OpenQuok CLI is …. [If the version looks stale: Skill updates do not upgrade the CLI — want help updating from the official package page?] [If connected: You're authenticated; workspace is …. | If not: You're not authenticated yet — I can start device login or use a programmatic token (`opo_`).]\n\nAfter this opening message, normal persona and task help are fine. Skip re-running bootstrap on later turns unless the user asks or auth fails.\n\n| Property | Value |\n|----------|-------|\n| **name** | openquok |\n| **description** | AI-ready social scheduling via the `openquok` CLI (global binary — separate from this skill): posts, integrations, media, analytics. |\n| **allowed-tools** | Bash(openquok:*) |\n\n---\n\n## ⚠️ Hard Rules (Read First)\n\n**0 — Session opening.** Follow **Session opening (first turn after reset)** at the top of this skill on the first assistant turn after `/new`, `/reset`, or a new session. Skills do not install or upgrade the `openquok` binary.\n\n**Links:** [npm `@openquok/auto-cli`](https://www.npmjs.com/package/@openquok/auto-cli) · [monorepo](https://github.com/Ratimon/openquok-monorepo/) · [CLI package](https://github.com/Ratimon/openquok-monorepo/tree/main/agent) · [openquok.com](https://www.openquok.com/)\n\n**1 — Auth before API work.** Any command that calls the API needs valid credentials. After bootstrap, re-check only when a command fails with auth errors.\n\n**2 — Media via workspace upload.** Every `-m` / `--media` / JSON `media[]` entry must be `{id, path}` from `openquok upload` or `openquok upload-from-url`. Never pass raw local paths or bare CDN URLs.\n\n```bash\nmedia_json() { openquok upload \"$1\" | jq -c '[{id: .data.id, path: (.data.path // .data.filePath)}]'; }\nopenquok posts:create -c \"…\" -s \"2026-01-01T12:00:00Z\" -i \"<uuid>\" -m \"$(media_json ./photo.jpg)\"\n```\n\nVerify upload stdout with `jq` (require `data.id` and `data.filePath`). Pass `filePath` as `media[].path`. Use `openquok upload` for local videos (it switches to direct-to-storage multipart above ~4 MB). Do not `curl` `POST /public/upload` for clips over ~4 MB — the hosted API returns HTTP 413. Remote assets: `openquok upload-from-url \"https://…\"`.\n\n---\n\n## Authentication\n\n| Order | Path | Use |\n|-------|------|-----|\n| 1 | **Device OAuth (two steps)** | Messaging agents (Telegram/Hermes): `auth:login --json --no-poll` → user opens `verification_uri_complete` → `auth:login:poll --device-code <device_code>` → `auth:status` |\n| 2 | **Programmatic token** | Headless or when device flow fails: `export OPENQUOK_API_KEY=opo_…` or `openquok auth:login --apiKey \"opo_…\"` |\n\n**Device OAuth on messaging hosts (required two-step):**\n\n```bash\nopenquok auth:login --json --no-poll\n# send verification_uri_complete to the user; wait until they confirm they authorized\nopenquok auth:login:poll --device-code \"<device_code from stdout>\"\nopenquok auth:status\n```\n\n- Tokens: [OpenQuok dashboard](https://www.openquok.com/) → **Settings → Developers → Access** → **Generate / Rotate token** (shown once).\n- Never invent verification URLs, user codes, or `device_code` — only values from `auth:login --json --no-poll` stdout.\n- Do **not** use `auth:login --json` alone on Telegram/Hermes; the host stops the shell after the first JSON and `~/.openquok/credentials.json` is never written.\n- Disk credentials in `~/.openquok/credentials.json` take precedence over `OPENQUOK_API_KEY` until `auth:logout`.\n- Workspace context: `openquok auth:workspace` → `{ workspace: { id, name } }`.\n- Optional: `OPENQUOK_API_URL`, `OPENQUOK_AUTH_SERVER` (local dev: `http://localhost:3111`).\n\nDetails: [resources/command-reference.md](./resources/command-reference.md#authentication).\n\n---\n\n## Shell safety\n\n- Run **fixed** `openquok` invocations; do not build commands by concatenating untrusted chat text into the shell.\n- Put captions and JSON payloads in **quoted** flags, heredocs, or files — not bare `$USER_INPUT` expansions.\n- Treat integration UUIDs, post IDs, and schedule times as opaque strings; reject values with shell metacharacters before use.\n\n---\n\n## Workflow\n\n| Step | Action |\n|------|--------|\n| 1 | Session opening (Rule 0): shell version/auth check, then one OpenQuok-bot greeting |\n| 2 | `openquok integrations:groups` when the workspace uses channel groups; then `integrations:list` (optionally `--group <id>`) → `integrations:settings <uuid>` per channel |\n| 3 | `integrations:trigger <uuid> <method> -d '{}'` when `output.tools` requires it |\n| 4 | `upload` / `upload-from-url` for media; ask user for file or direct image URL if missing in chat |\n| 5 | `posts:create` / `posts:status`; agent drafts: `-t draft` + `--note`; TikTok inbox/private drafts: `--note` with finish-in-app checklist; update with `posts:review-todo` |\n| 6 | `analytics:platform` / `analytics:post` with `-d 7` \\| `30` \\| `90` |\n| 7 | Missing release id: `posts:missing` → `posts:connect --release-id` |\n\nConnect new channels in the web app; the CLI only uses UUIDs from `integrations:list`.\n\n### Integration discovery\n\n```bash\nopenquok integrations:list\nopenquok integrations:list --group <customer-group-id>\nopenquok integrations:groups\nopenquok integrations:settings <integration-uuid>\nopenquok integrations:trigger <integration-uuid> <method-name> -d '{}'\n```\n\nUse `integrations:groups` to list channel groups (`{id, name}`), then filter channels with `integrations:list --group`. Full flag reference: [resources/command-reference.md](./resources/command-reference.md#integrations).\n\n---\n\n## Posting essentials\n\n```bash\n# Scheduled post\nopenquok posts:create -c \"Caption\" -s \"2026-01-01T12:00:00Z\" -i \"<uuid>\"\n\n# Draft + human checklist\nopenquok posts:create -c \"…\" -s \"…\" -t draft -i \"<uuid>\" --note \"Check CTA before schedule\"\n\n# Per-channel captions (multi integration)\nopenquok posts:create -s \"…\" -i \"<uuid-a>,<uuid-b>\" \\\n  --bodiesByIntegrationId '{\"<uuid-a>\":\"Short\",\"<uuid-b>\":\"Long\"}'\n\n# Provider fields (confirm keys via integrations:settings)\nopenquok posts:create -c \"…\" -s \"…\" --settings '{\"post_type\":\"post\"}' -i \"<uuid>\"\n\n# Full API body\nopenquok posts:create --json ./examples/threads-text-only.json\n```\n\n- Flag-based create **requires** `-s` (ISO-8601) unless `--json` includes `scheduledAt`.\n- `--settings` merges into `providerSettingsByIntegrationId` for each `-i` UUID; per-UUID maps use `--providerSettingsByIntegrationId`. See [resources/provider-settings.md](./resources/provider-settings.md).\n- Repeated `-c` (+ optional `-m`, `-d` in **milliseconds**) can build follow-up segments — for Meta Threads/Instagram follow-ups prefer nested `threads` / `instagram` buckets in channel examples.\n\nCommand surface: [resources/command-reference.md](./resources/command-reference.md).\n\n---\n\n## Plugs (internal and global)\n\nOpenQuok automates post-publish engagement with two plug types (included on paid plans):\n\n| Type | What it does | CLI |\n| --- | --- | --- |\n| **Internal plugs** | Same-account delayed reply (Threads) or actions from other connected channels (comment, repost, reshare) | Yes — set on `posts:create` via `providerSettingsByIntegrationId` |\n| **Global plugs** | Channel rules that trigger a reply/repost when likes hit a threshold (checks every 6h, up to 3 runs) | Yes — `plugs:catalog`, `plugs:list`, `plugs:upsert`, `plugs:activate`, `plugs:delete` |\n\nSupported channels: **Threads**, **X**, **LinkedIn**, **LinkedIn Page** (not Facebook, Instagram, YouTube, or TikTok).\n\n```bash\n# Internal plug — cross-account Threads comment (see examples/)\nopenquok posts:create --json ./examples/threads-cross-account-plug.json\n\n# Internal plug — same-account Threads delayed reply\nopenquok posts:create --json ./examples/threads-engagement-plug.json\n\n# Global plug — auto-reply when likes reach threshold (channel-level rule)\nopenquok plugs:catalog\nopenquok plugs:upsert <integration-id> --func autoPlugPost \\\n  --fields '[{\"name\":\"likesAmount\",\"value\":\"100\"},{\"name\":\"post\",\"value\":\"Thanks for reading!\"}]'\n```\n\nFull catalog, provider matrix, and global-plug web setup: [resources/plugs.md](./resources/plugs.md). Setting keys: [resources/provider-settings.md](./resources/provider-settings.md#internal-plugs).\n\n---\n\n## Channels (Meta)\n\nRun `integrations:settings <uuid>` for `rules`, `maxLength`, and `tools`. Match the user’s goal to the **Agent tasks** table in each channel file; publish keys and recipes are there.\n\nProvider settings overview: [resources/provider-settings.md](./resources/provider-settings.md).\n\n| Channel | `identifier` | User intents (see file) | Examples |\n|---------|----------------|-------------------------|----------|\n| Threads | `threads` | text/media/carousel, reply chain, finisher, internal plugs, global plugs, missing post | [threads-examples.md](./resources/threads-examples.md) |\n| Facebook Page | `facebook` | text, link preview, photo, carousel, Reel, comments | [facebook-examples.md](./resources/facebook-examples.md) |\n| Instagram Login | `instagram-standalone` | feed, carousel, Reel, Story, trial reel, comments | [instagram-standalone-examples.md](./resources/instagram-standalone-examples.md) |\n| Instagram Page | `instagram-business` | same as standalone (Page-linked OAuth) | [instagram-business-examples.md](./resources/instagram-business-examples.md) |\n| YouTube | `youtube` | MP4 upload, title/privacy/tags/thumbnail, channel analytics | [youtube-examples.md](./resources/youtube-examples.md) |\n| TikTok | `tiktok` | direct publish, inbox upload (`UPLOAD`), private `SELF_ONLY` drafts, privacy, toggles, analytics | [tiktok-examples.md](./resources/tiktok-examples.md) |\n| LinkedIn | `linkedin` | personal profile posts, images, video, text comments, internal plugs | [linkedin-examples.md](./resources/linkedin-examples.md) |\n| LinkedIn Page | `linkedin-page` | Page picker, document carousel, internal + global plugs, Page + post analytics | [linkedin-page-examples.md](./resources/linkedin-page-examples.md) |\n| X | `x` | text/media, thread replies, finisher, reply settings, internal + global plugs, analytics | [x-examples.md](./resources/x-examples.md) |\n| Dev.to | `devto` | markdown article, title/tags/cover/canonical/org/series, `tags` + `organizations` tools, analytics | [devto-examples.md](./resources/devto-examples.md) |\n\nThreads publish failures: [threads-publish.md](./resources/threads-publish.md).\n\n---\n\n## More recipes\n\n[resources/patterns.md](./resources/patterns.md) — multi-attachment posts, `integrations:trigger`, JSON campaigns, internal plugs, length checks, batching, retries.\n\n[resources/plugs.md](./resources/plugs.md) — internal plugs (CLI) and global plugs (web app).\n\n---\n\n## Pitfalls\n\n| Symptom | Fix |\n|---------|-----|\n| API 401 / auth errors | Two-step device OAuth (`auth:login --json --no-poll` then `auth:login:poll`); or programmatic token (`opo_`); never fake device URLs |\n| Device login OK in browser but CLI has no credentials | Messaging host ended `auth:login --json` before polling — use `--no-poll` + `auth:login:poll`, or `auth:login --apiKey` |\n| Invalid or expired device code | Re-run `auth:login --json --no-poll`; use fresh `verification_uri_complete` (~30 min) |\n| Wrong channel | Re-fetch UUID from `integrations:list` |\n| Media rejected at publish | Rule 2: upload first; for Threads see [threads-publish.md](./resources/threads-publish.md) |\n| “Image” in chat, no file | Stop; get file path or `https://` URL for `upload-from-url` |\n| Empty upload / `Content-Length: 0` | Re-upload a non-empty asset |\n| Unknown `integrations:trigger` | Method must appear in `output.tools` |\n| `--settings` parse error | Single-quoted JSON: `'{\"post_type\":\"post\"}'` |\n| Thread timing wrong | `-d` is **milliseconds**, not minutes |\n| Unknown global plug `func` | Run `plugs:catalog` and use `methodName` (e.g. `autoPlugPost`, `autoRepostPost`) |\n| Analytics rejected | `-d` must be **7**, **30**, or **90** |\n| Env key ignored | `auth:logout` if disk credentials exist |\n| Old CLI / wrong verify host | Compare `openquok --version` with the current release on the [CLI package page](https://www.npmjs.com/package/@openquok/auto-cli); reinstall or upgrade the binary there — skill install does not update it |\n\nFile v1.0.7:_meta.json\n\n{\n  \"ownerId\": \"kn7bz73j78bvq5mfqy2c9msscs896h8e\",\n  \"slug\": \"openquok-core\",\n  \"version\": \"1.0.7\",\n  \"publishedAt\": 1789017272078\n}\n\nFile v1.0.7:resources/command-reference.md\n\n# OpenQuok CLI — command reference\n\nAgent-oriented reference for `@openquok/auto-cli` (`openquok`). Hard rules, auth, and workflows live in [SKILL.md](../SKILL.md).\n\n## Environment variables\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `OPENQUOK_API_KEY` | No* | — | Bearer `opo_` programmatic access token |\n| `OPENQUOK_API_URL` | No | `https://api.openquok.com` | API base (`{OPENQUOK_API_URL}/api/v1/...`) |\n| `OPENQUOK_AUTH_SERVER` | No | `https://cli-auth.openquok.com` | OAuth2 device-flow server (`/device/*`, `/health`) |\n\n\\*Either `OPENQUOK_API_KEY` or stored credentials from `openquok auth:login` is required. **Stored credentials take priority** over the env var until `auth:logout`.\n\n## Config\n\n```bash\nopenquok config:show\n```\n\nPrints resolved `api_url`, `auth_server_url`, deployment mode (`openquok_cloud` vs `custom`), and value sources — no secrets.\n\n## Authentication\n\n```bash\n# Messaging agents (Telegram/Hermes) — two steps; do not use auth:login --json alone\nopenquok auth:login --json --no-poll\nopenquok auth:login:poll --device-code \"<device_code from stdout>\"\n\n# CI / long-running shell — single process may use auth:login --json (polls until done)\nopenquok auth:login --json\n\nopenquok auth:login --apiKey \"opo_…\"   # fallback when device flow cannot complete\nopenquok auth:status\nopenquok auth:workspace             # { workspace: { id, name } } for current credentials\nopenquok auth:logout\n```\n\n- **Preference:** device OAuth before a programmatic token when the user can open a browser link.\n- **Messaging hosts:** `--json --no-poll` then `auth:login:poll` after the user authorizes — otherwise credentials are never stored.\n- **Agents:** forward `verification_uri_complete` from stdout only — never fabricate codes or URLs.\n- **Humans with TTY:** `openquok auth:login` without `--json` is fine locally.\n- **Session start:** see Rule 0 in [SKILL.md](../SKILL.md) — run version + `auth:status` (+ `auth:workspace` when connected) via shell before the first assistant message; greet as the OpenQuok bot, not the host persona.\n- **Invalid or expired code:** Re-run `auth:login --json --no-poll` and `auth:login:poll` with a fresh `device_code` (~30 min).\n\n\n## Integrations\n\n```bash\n# List all connected social channels (integration UUIDs)\nopenquok integrations:list\n\n# List integrations belonging to a specific channel group (customer)\nopenquok integrations:list --group <customer-group-id>\n\n# List all channel groups (customers) as {id, name}\nopenquok integrations:groups\n\n# Get posting rules, character limits, and settings schema for an integration\nopenquok integrations:settings <integration-uuid>\n\n# Trigger an allow-listed provider method to fetch dynamic data\nopenquok integrations:trigger <integration-uuid> <method-name> [--data '<json>' | -d '<json>']\n```\n\n- `integrations:groups` — channel groups (`integration_customers`); pass an `id` to `integrations:list --group`.\n- `integrations:settings` — rules, `maxLength`, settings schema, allow-listed `tools` (`methodName`, `dataSchema`). Publish-time keys per channel: [provider-settings.md](./provider-settings.md).\n- `integrations:trigger` — single allow-listed method; `--data` must be a JSON object when required. Live examples: Dev.to `tags` / `organizations`; LinkedIn `company` (URL in `--data`).\n- New channels are connected in the web app (OAuth, or a dashboard API key for Dev.to); the CLI uses integration UUIDs from `integrations:list`.\n\n## Posts\n\n```bash\n# List posts (default ±30 local calendar days from today)\nopenquok posts:list\nopenquok posts:list --start \"2026-01-01T00:00:00Z\" --end \"2026-02-01T00:00:00Z\"\n\n# Create or schedule posts (-s / scheduledAt is REQUIRED unless using --json)\nopenquok posts:create -c \"…\" -s \"2026-01-01T12:00:00Z\" -i \"<uuid>\"\nopenquok posts:create -c \"…\" -s \"…\" -t draft -i \"<uuid>\"\nopenquok posts:create -c \"…\" -s \"…\" -i \"<uuid>\" -m '<[{id,path}]>'\nopenquok posts:create -c \"main\" -c \"reply\" -s \"…\" -d 5000 -i \"<uuid>\"\nopenquok posts:create --json ./post.json\n\n# Manage post rows\nopenquok posts:status <post-id> --status draft\nopenquok posts:status <post-id> -s schedule\nopenquok posts:review-todo <post-id> --note \"…\"\nopenquok posts:delete <post-id>\n\n# Resolve missing release_id before per-post analytics\nopenquok posts:missing <post-id>\nopenquok posts:connect <post-id> --release-id \"<provider-release-id>\"\n```\n\n### `posts:list`\n\n- Default window: ±30 **local calendar** days from today (ISO on the wire).\n- Override: `--start` / `--end` (aliases `--startDate` / `--endDate`).\n- Filter: `-i` / `--integrations` / `--integrationIds` (CSV), `--customer` / `--customerGroupId`.\n\n### `posts:status`\n\n- Takes a **post row** id from `posts:list` (same as `posts:delete`).\n- Flips `draft` ↔ `scheduled` at the stored publish time.\n\n### `posts:missing` / `posts:connect`\n\n- Use when `release_id` is `\"missing\"`: list provider candidates, then link with `--release-id` (aliases `--releaseId`, `-r`) for per-post analytics.\n\n### Media flags (`-m` / `--media`)\n\n- Value must be a JSON array of `{ \"id\", \"path\" }` from `openquok upload` or `openquok upload-from-url` (see Rule 2 in SKILL.md).\n- **Thread-style posts:** repeated `-c` for segments; optional repeated `-m` pairs with leading segments. `-d` is **milliseconds** between segments (default 5000).\n\n### `--json` / `-j`\n\n- Full `POST /public/posts` payload: `scheduledAt`, `status`, `bodiesByIntegrationId`, `providerSettingsByIntegrationId`, `media`, tags, etc.\n\n## Analytics\n\n```bash\n# Platform-level metrics for a connected channel (7, 30, or 90 days)\nopenquok analytics:platform <integration-uuid> [--days 7|30|90]\n\n# Per-post metrics for a published post row\nopenquok analytics:post <post-id> [--days 7|30|90]\n```\n\n- `--days` / `-d` must be **7**, **30**, or **90** (default 7).\n- `analytics:post` returns `[]` for drafts/qu\n\nArchive v1.0.6: 62 files, 59727 bytes\n\nFiles: resources/command-reference.md (7184b), resources/devto-examples.md (4618b), resources/examples/devto-article-title-tags.json (508b), resources/examples/devto-canonical.json (505b), resources/examples/devto-organization.json (515b), resources/examples/devto-series.json (413b), resources/examples/EXAMPLES.md (5902b), resources/examples/facebook-follow-up-comment-with-image.json (519b), resources/examples/facebook-follow-up-comment.json (363b), resources/examples/facebook-link-preview.json (269b), resources/examples/facebook-multi-photo.json (308b), resources/examples/facebook-reel.json (230b), resources/examples/facebook-story.json (314b), resources/examples/facebook-text-only.json (148b), resources/examples/facebook-with-image.json (222b), resources/examples/instagram-carousel.json (424b), resources/examples/instagram-feed-post.json (329b), resources/examples/instagram-follow-up-comments.json (529b), resources/examples/instagram-reel.json (218b), resources/examples/instagram-story.json (314b), resources/examples/instagram-trial-reel.json (465b), resources/examples/linkedin-document-carousel.json (587b), resources/examples/linkedin-follow-up-comment.json (367b), resources/examples/linkedin-page-document-carousel.json (527b), resources/examples/linkedin-text-post.json (138b), resources/examples/linkedin-with-video.json (243b), resources/examples/multi-platform-campaign.json (988b), resources/examples/threads-cross-account-plug.json (613b), resources/examples/threads-engagement-plug.json (436b), resources/examples/threads-follow-up-replies.json (476b), resources/examples/threads-follow-up-reply-with-image.json (533b), resources/examples/threads-media-carousel.json (301b), resources/examples/threads-text-only.json (140b), resources/examples/threads-thread-finisher.json (474b), resources/examples/threads-with-image.json (228b), resources/examples/tiktok-photo-carousel.json (527b), resources/examples/tiktok-private-draft.json (626b), resources/examples/tiktok-upload-inbox.json (460b), resources/examples/tiktok-video-direct-post.json (485b), resources/examples/x-cross-account-repost.json (501b), resources/examples/x-follow-up-replies.json (349b), resources/examples/x-follow-up-reply-with-image.json (494b), resources/examples/youtube-flat-settings.json (426b), resources/examples/youtube-video-title-privacy.json (444b), resources/examples/youtube-with-tags.json (579b), resources/examples/youtube-with-thumbnail.json (486b), resources/facebook-examples.md (5302b), resources/instagram-business-examples.md (3193b), resources/instagram-standalone-examples.md (3135b), resources/linkedin-examples.md (3720b), resources/linkedin-page-examples.md (2091b), resources/patterns.md (3515b), resources/plugs.md (4828b), resources/provider-settings.md (11803b), resources/threads-examples.md (6312b), resources/threads-publish.md (2024b), resources/tiktok-examples.md (7439b), resources/x-examples.md (6015b), resources/youtube-examples.md (3647b), skill-card.md (2534b), SKILL.md (15154b), _meta.json (132b)\n\nArchive v1.0.5: 58 files, 57554 bytes\n\nFiles: resources/command-reference.md (7184b), resources/devto-examples.md (4618b), resources/examples/devto-article-title-tags.json (508b), resources/examples/devto-canonical.json (505b), resources/examples/devto-organization.json (515b), resources/examples/devto-series.json (413b), resources/examples/EXAMPLES.md (5219b), resources/examples/facebook-follow-up-comment.json (363b), resources/examples/facebook-link-preview.json (269b), resources/examples/facebook-multi-photo.json (308b), resources/examples/facebook-reel.json (230b), resources/examples/facebook-story.json (314b), resources/examples/facebook-text-only.json (148b), resources/examples/facebook-with-image.json (222b), resources/examples/instagram-carousel.json (424b), resources/examples/instagram-feed-post.json (329b), resources/examples/instagram-follow-up-comments.json (529b), resources/examples/instagram-reel.json (218b), resources/examples/instagram-story.json (314b), resources/examples/instagram-trial-reel.json (465b), resources/examples/linkedin-document-carousel.json (587b), resources/examples...","readmeExcerpt":"Skill: OpenQuok Core Owner: ratimon Summary: Schedule and manage social posts with the openquok CLI — authenticate, upload media, create drafts and scheduled posts, configure internal plugs, and read channel analytics for integrations in your OpenQuok workspace. Tags: latest:1.0.9 Version history: v1.0.9 | 2026-09-27T14:11:00.536Z | auto openquok-core 1.0.9 - Added Bluesky support: new Bluesky example resources and c","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"openquok --version\nopenquok auth:status"},{"language":"bash","snippet":"media_json() { openquok upload \"$1\" | jq -c '[{id: .data.id, path: (.data.path // .data.filePath)}]'; }\nopenquok posts:create -c \"…\" -s \"2026-01-01T12:00:00Z\" -i \"<uuid>\" -m \"$(media_json ./photo.jpg)\""},{"language":"bash","snippet":"openquok auth:login --json --no-poll\n# send verification_uri_complete to the user; wait until they confirm they authorized\nopenquok auth:login:poll --device-code \"<device_code from stdout>\"\nopenquok auth:status"},{"language":"bash","snippet":"openquok integrations:list\nopenquok integrations:list --group <customer-group-id>\nopenquok integrations:groups\nopenquok integrations:settings <integration-uuid>\nopenquok integrations:trigger <integration-uuid> <method-name> -d '{}'"},{"language":"bash","snippet":"# Scheduled post\nopenquok posts:create -c \"Caption\" -s \"2026-01-01T12:00:00Z\" -i \"<uuid>\"\n\n# Draft + human checklist\nopenquok posts:create -c \"…\" -s \"…\" -t draft -i \"<uuid>\" --note \"Check CTA before schedule\"\n\n# Per-channel captions (multi integration)\nopenquok posts:create -s \"…\" -i \"<uuid-a>,<uuid-b>\" \\\n  --bodiesByIntegrationId '{\"<uuid-a>\":\"Short\",\"<uuid-b>\":\"Long\"}'\n\n# Provider fields (confirm keys via integrations:settings)\nopenquok posts:create -c \"…\" -s \"…\" --settings '{\"post_type\":\"post\"}' -i \"<uuid>\"\n\n# Full API body\nopenquok posts:create --json ./examples/threads-text-only.json"},{"language":"bash","snippet":"# Internal plug — cross-account Threads comment (see examples/)\nopenquok posts:create --json ./examples/threads-cross-account-plug.json\n\n# Internal plug — same-account Threads delayed reply\nopenquok posts:create --json ./examples/threads-engagement-plug.json\n\n# Global plug — auto-reply when likes reach threshold (channel-level rule)\nopenquok plugs:catalog\nopenquok plugs:upsert <integration-id> --func autoPlugPost \\\n  --fields '[{\"name\":\"likesAmount\",\"value\":\"100\"},{\"name\":\"post\",\"value\":\"Thanks for reading!\"}]'"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: openquok-core\ndescription: >-\n  Schedule and manage social posts with the openquok CLI — authenticate, upload media, create drafts and scheduled posts, configure internal plugs, and read channel analytics for integrations in your OpenQuok workspace.\nhomepage: https://www.npmjs.com/package/@openquok/auto-cli\nversion: 1.0.0\nlicense: MIT\ncompatibility: Requires the global openquok CLI on PATH (see homepage). Installing this skill does not add the binary.\nprerequisites:\n  commands: [openquok]\nmetadata: {\"openclaw\":{\"emoji\":\"📮\",\"always\":true,\"requires\":{\"bins\":[\"openquok\"]},\"homepage\":\"https://www.npmjs.com/package/@openquok/auto-cli\"},\"hermes\":{\"tags\":[\"social-media\",\"openquok\",\"scheduling\"],\"category\":\"social-media\",\"requires_toolsets\":[\"terminal\"]},\"grok-bot\":{\"tags\":[\"social-media\",\"openquok\",\"scheduling\"],\"category\":\"social-media\",\"requires_toolsets\":[\"terminal\"],\"workspace_skill_path\":\"/workspace/openquok-core/SKILL.md\"},\"thinkrail\":{\"tags\":[\"social-media\",\"openquok\",\"scheduling\"],\"category\":\"social-media\",\"requires_toolsets\":[\"terminal\"],\"skill_paths\":[\"~/.pi/agent/skills/openquok-core/SKILL.md\",\".pi/skills/openquok-core/SKILL.md\"]}}\n---\n\n<!-- SPDX-FileCopyrightText: 2026 Rati Montreewat -->\n<!-- SPDX-License-Identifier: MIT -->\n\n## Session opening (first turn after reset)\n\n**When:** first assistant reply after `/new`, `/reset`, a new channel thread, or a “new session started” notice.\n\n**On that turn only:** use the OpenQuok bot voice below instead of a generic host welcome. Do **not** reuse this block on later turns.\n\n**One message only.** Run shell (below), then send **exactly one** assistant message. Forbidden on this turn:\n\n- A persona line before tools (e.g. “Hello, … I’m Atlas … What should we focus on?”).\n- A second message with only CLI version (e.g. “The OpenQuok CLI version is 0.0.6.”).\n- Repeating the host greeting after the system “new session started” line.\n\n**Shell (before any user-visible text):**\n\n```bash\nopenquok --version\nopenquok auth:status\n```\n\nIf `auth:status` shows `\"connected\": true`, also run `openquok auth:workspace`.\n\n**Required opening sentence (verbatim start):** `Hi, I am the OpenQuok bot.`\n\n**Same message must also include:**\n\n1. Installed CLI version from `openquok --version`.\n2. If the user may be on an old build: note that skill install does not upgrade the CLI and offer to walk through upgrade using the [CLI package page](https://www.npmjs.com/package/@openquok/auto-cli) — only after they agree.\n3. Auth: if connected, say you are authenticated and name **`workspace.name`**; if not, say not authenticated and offer the **two-step device flow** (below) or a programmatic token (`opo_`). **Never** run `auth:login --json` without `--no-poll` on messaging hosts — the shell exits before credentials are stored.\n\n**Fill-in template (one paragraph — replace `…` from shell output):**\n\n> Hi, I am the OpenQuok bot. OpenQuok CLI is …. [If the version looks stale: Skill updates do not upgrade the CLI — want help up"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7bz73j78bvq5mfqy2c9msscs896h8e\",\n  \"slug\": \"openquok-core\",\n  \"version\": \"1.0.9\",\n  \"publishedAt\": 1790518260536\n}"},{"path":"resources/bluesky-examples.md","content":"# Bluesky — CLI examples\n\n```bash\nBSKY_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"bluesky\") | .id')\nopenquok integrations:settings \"$BSKY_ID\"\n```\n\nRun `integrations:settings` for `output.maxLength` (300) and `rules`. Settings mechanics: [provider-settings.md](./provider-settings.md).\n\nJSON recipes: [examples/EXAMPLES.md](./examples/EXAMPLES.md#bluesky).\n\n## Supported features\n\n| Feature | Supported | Notes |\n| --- | --- | --- |\n| Text-only post | Yes | No attachment required |\n| Images | Yes | Up to **4** per main post or follow-up — upload first (Rule 2) |\n| Video | Yes | **1** MP4 per post — never mixed with images |\n| 300-grapheme cap | Yes | Main `body`, each `bluesky.replies[].message` on schedule |\n| Scheduled follow-up replies | Yes | `bluesky.replies[]` with `delaySeconds`; optional `media` per reply |\n| Mention autocomplete | Yes | Composer `@handle`; publish uses facets |\n| Link card embed | Yes | `bluesky.linkUrl` (+ optional title/description) on text-only posts — not with media or quote |\n| Quote post | Yes | `bluesky.quoteUrl` (`bsky.app` or AT URI) — not with media or link card |\n| Thread gate | Yes | `bluesky.threadGate` — who can reply after publish |\n| Video limits | Yes | One MP4 — max **300 MB**, **10** minutes |\n| Global plugs | Yes | Auto-repost / auto-plug on like threshold — channel **Plugs** tab, not create-post payload |\n| Channel / post analytics | Yes | `analytics:platform` / `analytics:post` — likes, replies, reposts, quotes via public App View |\n| Cross-post to other channels | Yes | Separate `-i` UUIDs per channel |\n\n## Agent tasks\n\n| User wants to… | JSON example |\n| --- | --- |\n| Post text only | [bluesky-text-only.json](./examples/bluesky-text-only.json) |\n| Post with images | [bluesky-images.json](./examples/bluesky-images.json) |\n| Schedule a follow-up reply | [bluesky-follow-up.json](./examples/bluesky-follow-up.json) |\n| Check channel limits | `openquok integrations:settings \"$BSKY_ID\"` |\n\n## Provider settings (`bluesky` bucket)\n\nUse nested keys under `bluesky` in `--providerSettingsByIntegrationId` (matches composer and orchestrator).\n\n| Key | Shape | When |\n| --- | --- | --- |\n| `bluesky.threadGate` | `\"everyone\"` \\| `\"mentioned\"` \\| `\"following\"` \\| `\"followers\"` \\| `\"nobody\"` | Who can reply (default `everyone`) |\n| `bluesky.linkUrl` | HTTPS URL | Optional link card — text-only; optional `linkTitle`, `linkDescription` |\n| `bluesky.quoteUrl` | `bsky.app` or AT post URI | Quote another post — not with media or link card |\n| `bluesky.replies` | `[{ \"id\": \"…\", \"message\": \"…\", \"delaySeconds\": 60, \"media\": [...] }]` | Follow-up replies after the root post publishes |\n\nNo flat CLI aliases — compose settings and follow-ups use the `bluesky` bucket only.\n\n### Reply media (`bluesky.replies[].media`)\n\nOptional on each reply row. Same shapes as the main post. Upload first (Rule 2); the worker resolves `path` to a public URL before upload to the host.\n\n- Up to four images or one MP4 per reply "},{"path":"resources/command-reference.md","content":"# OpenQuok CLI — command reference\n\nAgent-oriented reference for `@openquok/auto-cli` (`openquok`). Hard rules, auth, and workflows live in [SKILL.md](../SKILL.md).\n\n## Environment variables\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `OPENQUOK_API_KEY` | No* | — | Bearer `opo_` programmatic access token |\n| `OPENQUOK_API_URL` | No | `https://api.openquok.com` | API base (`{OPENQUOK_API_URL}/api/v1/...`) |\n| `OPENQUOK_AUTH_SERVER` | No | `https://cli-auth.openquok.com` | OAuth2 device-flow server (`/device/*`, `/health`) |\n\n\\*Either `OPENQUOK_API_KEY` or stored credentials from `openquok auth:login` is required. **Stored credentials take priority** over the env var until `auth:logout`.\n\n## Config\n\n```bash\nopenquok config:show\n```\n\nPrints resolved `api_url`, `auth_server_url`, deployment mode (`openquok_cloud` vs `custom`), and value sources — no secrets.\n\n## Authentication\n\n```bash\n# Messaging agents (Telegram/Hermes) — two steps; do not use auth:login --json alone\nopenquok auth:login --json --no-poll\nopenquok auth:login:poll --device-code \"<device_code from stdout>\"\n\n# CI / long-running shell — single process may use auth:login --json (polls until done)\nopenquok auth:login --json\n\nopenquok auth:login --apiKey \"opo_…\"   # fallback when device flow cannot complete\nopenquok auth:status\nopenquok auth:workspace             # { workspace: { id, name } } for current credentials\nopenquok auth:logout\n```\n\n- **Preference:** device OAuth before a programmatic token when the user can open a browser link.\n- **Messaging hosts:** `--json --no-poll` then `auth:login:poll` after the user authorizes — otherwise credentials are never stored.\n- **Agents:** forward `verification_uri_complete` from stdout only — never fabricate codes or URLs.\n- **Humans with TTY:** `openquok auth:login` without `--json` is fine locally.\n- **Session start:** see Rule 0 in [SKILL.md](../SKILL.md) — run version + `auth:status` (+ `auth:workspace` when connected) via shell before the first assistant message; greet as the OpenQuok bot, not the host persona.\n- **Invalid or expired code:** Re-run `auth:login --json --no-poll` and `auth:login:poll` with a fresh `device_code` (~30 min).\n\n\n## Integrations\n\n```bash\n# List all connected social channels (integration UUIDs)\nopenquok integrations:list\n\n# List integrations belonging to a specific channel group (customer)\nopenquok integrations:list --group <customer-group-id>\n\n# List all channel groups (customers) as {id, name}\nopenquok integrations:groups\n\n# Get posting rules, character limits, and settings schema for an integration\nopenquok integrations:settings <integration-uuid>\n\n# Trigger an allow-listed provider method to fetch dynamic data\nopenquok integrations:trigger <integration-uuid> <method-name> [--data '<json>' | -d '<json>']\n```\n\n- `integrations:groups` — channel groups (`integration_customers`); pass an `id` to `integrations:list --group`.\n- `integrations:settings` — rules, `maxLe"},{"path":"resources/devto-examples.md","content":"# Dev.to (`devto`) — CLI examples\n\n```bash\nDEVTO_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier==\"devto\") | .id')\nopenquok integrations:settings \"$DEVTO_ID\"\n```\n\nConnect the channel in the OpenQuok dashboard with a personal API key (DEV Settings → Extensions). There is no public OAuth start URL.\n\nRun `integrations:settings` for `output.rules`, `output.maxLength`, typed `settingsSchema`, and allow-listed `output.tools` (`tags`, `organizations`).\n\nSettings mechanics: [provider-settings.md](./provider-settings.md). JSON recipes: [examples/EXAMPLES.md](./examples/EXAMPLES.md#devto).\n\n## Supported features\n\n| Feature | Supported | Notes |\n| --- | --- | --- |\n| Markdown article body | Yes | Root `-c` caption (up to 100,000 characters) |\n| Title | Yes | Required; min 2 characters (`title`) |\n| Tags | Yes | Up to 4 names; strings or `{ value, label }` |\n| Cover image | Yes | `main_image` / `mainImage` `{ path }` from a prior `upload` |\n| Canonical URL | Yes | `canonical` (aliases `canonical_url`, `canonicalUrl`) |\n| Organization | Yes | Numeric id from `integrations:trigger … organizations` |\n| Series | Yes | Free-text `series`; Dev.to creates the series if missing |\n| Tag / org lookup | Yes | `integrations:trigger` `tags` and `organizations` |\n| Channel / article analytics | Yes | `analytics:platform` and `analytics:post` — page views, reactions, comments |\n| Follow-up comments | No | Out of scope |\n| Public OAuth connect | No | Dashboard API key only |\n\n## Agent tasks\n\n| User wants to… | JSON example |\n| --- | --- |\n| Schedule a markdown article with title and tags | [devto-article-title-tags.json](./examples/devto-article-title-tags.json) |\n| Add the article to a series | [devto-series.json](./examples/devto-series.json) |\n| Syndicate with a canonical URL | [devto-canonical.json](./examples/devto-canonical.json) |\n| Publish under an organization with a cover | [devto-organization.json](./examples/devto-organization.json) |\n| List tag suggestions | `openquok integrations:trigger \"$DEVTO_ID\" tags` |\n| List organizations the key can publish under | `openquok integrations:trigger \"$DEVTO_ID\" organizations` |\n| See the typed settings schema | `openquok integrations:settings \"$DEVTO_ID\"` |\n| Track account performance | [Discover integration](#discover-integration) → `analytics:platform` |\n| Inspect a published article | [Post insights](#post-insights) |\n\n## Provider settings\n\nFlat JSON on `--settings` or inside `--providerSettingsByIntegrationId` for the Dev.to UUID. Nested `devto.*` matches the web composer bucket.\n\n| Key | Values | When |\n| --- | --- | --- |\n| `title` | string (min 2 chars) | Required for valid publish |\n| `tags` | strings or `[{ \"value\": \"…\", \"label\": \"…\" }]` | Optional; max 4 |\n| `canonical` | URL string | Optional syndication URL |\n| `canonical_url` / `canonicalUrl` | URL string | Aliases for `canonical` |\n| `organization` | integer id | Optional; from `organizations` tool |\n| `organization_id` / `organizationId` | i"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":2141,"uniquenessScore":38,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T21:52:28.097Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-10T21:52:28.097Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T00:32:18.818Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}