Skip to content

X

OpenQuok CLI examples for X — tweets, media, thread replies, and analytics.

2 min read

Connect your agent today

Draft from chat, review in your calendar, and publish only what you approve.

Start for $0

Channel quick reference

PropertyValue
Provider identifierx
Max content length280 weighted (4000 when Verified)
Required attachmentsNone — text-only posts publish
OAuthOAuth 1.0a (Native App, Read + Write)
OAuth setupX setup guide
X_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier=="x") | .id')

Simple text post

openquok posts:create 
  -s "2026-01-15T10:00:00Z" 
  -t schedule 
  -c "Hello from OpenQuok!" 
  -i "$X_ID"

Post with images

X accepts up to four images per post. Upload assets and pass returned id/path values:

MEDIA=$(openquok upload ./hero.jpg | jq -c '[{id: .data.id, path: .data.filePath}]')

openquok posts:create 
  -s "2026-01-15T10:00:00Z" 
  -t schedule 
  -c "Launch day." 
  -i "$X_ID" 
  -m "$MEDIA"

Scheduled reply chain (thread)

providerSettings.x.replies[] carries follow-up comments that are published as quote-less replies after the root tweet:
openquok posts:create 
  -s "2026-01-15T10:00:00Z" 
  -c "Thread 1/2: Why we built OpenQuok" 
  -i "$X_ID" 
  --providerSettingsByIntegrationId "$(jq -nc --arg id "$X_ID" '
    {
      ($id): {
        x: {
          replies: [
            { message: "Thread 2/2: What is next", delaySeconds: 120 }
          ]
        }
      }
    }
  ')"

Thread reply with images

Upload first, then attach up to four images per reply row on x.replies[]:

REPLY_MEDIA=$(openquok upload ./payoff.jpg | jq -c '[{id: .data.id, path: (.data.path // .data.filePath)}]')

openquok posts:create 
  -s "2026-01-15T10:00:00Z" 
  -c "1/2 — setup" 
  -i "$X_ID" 
  --providerSettingsByIntegrationId "$(jq -nc --arg id "$X_ID" --argjson media "$REPLY_MEDIA" '
    {
      ($id): {
        x: {
          replies: [
            { message: "2/2 — payoff", delaySeconds: 90, media: $media }
          ]
        }
      }
    }
  ')"

Thread finisher

Enable a closing reply with x.enabled and x.message:

openquok posts:create 
  -s "2026-01-15T10:00:00Z" 
  -c "Main tweet" 
  -i "$X_ID" 
  --providerSettingsByIntegrationId "$(jq -nc --arg id "$X_ID" '
    {
      ($id): {
        x: {
          enabled: true,
          message: "Thanks for reading!"
        }
      }
    }
  ')"

Compose settings (reply audience, community, labels)

openquok posts:create 
  -s "2026-01-15T10:00:00Z" 
  -c "Community update" 
  -i "$X_ID" 
  --providerSettingsByIntegrationId "$(jq -nc --arg id "$X_ID" '
    {
      ($id): {
        x: {
          whoCanReplyPost: "following",
          madeWithAi: true
        }
      }
    }
  ')"

Flat CLI keys are also accepted (e.g. who_can_reply_post, made_with_ai).

Cross-account repost

providerSettings.x.crossAccountPlugs reposts the published tweet from other X channels in the same workspace. Use plug name x-repost-post-users with acting channel UUIDs in integrationIds.
X_PUBLISH_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier=="x") | .id' | head -n1)
X_OTHER_ID=$(openquok integrations:list | jq -r '.[] | select(.identifier=="x") | .id' | sed -n '2p')

openquok posts:create 
  -s "2026-01-15T10:00:00Z" 
  -c "Main tweet from our brand account" 
  -i "$X_PUBLISH_ID" 
  --providerSettingsByIntegrationId "$(jq -nc 
    --arg publish "$X_PUBLISH_ID" 
    --arg other "$X_OTHER_ID" '
    {
      ($publish): {
        x: {
          crossAccountPlugs: [
            {
              plugName: "x-repost-post-users",
              enabled: true,
              delayMs: 0,
              integrationIds: [$other],
              fields: {}
            }
          ]
        }
      }
    }
  ')"

Analytics

openquok analytics:platform "$X_ID" -d 7

When DISABLE_X_ANALYTICS is true on the backend, analytics return empty series.

Search documentation
Find a docs page
Discord Support