extension-posting-to-x
MANDATORY recipe for every Caffeine build that posts to X (Twitter). The ONLY supported path is the `x-client` mops package with OAuth 2.0 PKCE. Hand-rolling `ic.http_request` or `icBooking.http_request` calls to `api.x.com/2/tweets`, `api.x.com/2/oauth2/token`, or any other X endpoint is a FORBIDDEN anti-pattern — it bypasses bearer auth, replication-cost safeguards, and `x-client`'s null-field handling. Load this skill whenever the user, spec, or any prior task mentions tweeting, live-tweeting
Security Assessment
Detected risks:
About extension-posting-to-x
This extension is the mandatory recipe for any Caffeine build that publishes content to an X (Twitter) account. The only supported path is the x-client mops package (generated Motoko bindings for the X API v2, including TweetsApi.createPosts and related calls) driven by an OAuth 2.0 Authorization Code with PKCE flow. Hand-rolling ic.http_request calls to api.x.com endpoints is treated as a forbidden anti-pattern because it leaks the OAuth bearer across replicated outcalls (a security and roughly 13x billing problem) and bypasses x-client's handling of X's null-field semantics, where X returns null for absent fields and rejects explicit null on writes. The skill is scoped to X writes only (tweet, retweet, quote-tweet, status update, live-tweet); reading from X timelines, search, or user lookup stays on the separate extension-http-outcalls path.
The auth model uses per-user bearer tokens rather than a single canister-wide key: each end-user authorises the canister independently, and the canister stores their access_token plus refresh_token keyed by caller Principal. Tokens expire in roughly two hours and are refreshed silently via the refresh_token, which rotates on every refresh and must always be persisted anew. An X Developer App Client ID (a public identifier, not a secret) is required, with three variants the spec can pick from: an admin Client ID registered once by the canister owner and shared by all users (the recommended default), a per-user Client ID where each tenant brings their own app to avoid sharing rate-limit quota, and a fallback that accepts both with an admin default users may override.
The extension-authorization skill is a hard prerequisite for every variant, since X requires a signed-in, non-anonymous caller for each meaningful endpoint and the admin/fallback Client ID setters are gated on the #admin role; it supplies the Internet Identity login flow and the backend caller/role infrastructure. Configuration must pin Config is_replicated = ?false, x-client must be at least version 0.2.3 (added via mops add [email protected]), and the requested OAuth scopes cover both authorise-time consent and posting. Token values must never be returned by a getter or written to logs.
FAQ
Why can't I just call api.x.com directly with ic.http_request?
Raw HTTP outcalls to api.x.com are a forbidden anti-pattern: they leak the OAuth bearer across replicated outcalls (a security and ~13x billing problem) and bypass x-client's handling of X's null-field behavior. The x-client mops package is the only supported path.
What authentication does posting to X use?
It uses per-user OAuth 2.0 Authorization Code with PKCE; each end-user authorises the canister and their access_token plus refresh_token are stored keyed by caller Principal. There is no canister-wide bearer.
Which Client ID variant should I choose?
The admin Client ID, registered once by the canister owner and shared by all users, is the recommended default. Per-user Client IDs suit multi-tenant apps that must not share rate-limit quota, and a fallback variant accepts an admin default that individual users can override.
Is extension-authorization required?
Yes, for all variants. X requires a signed-in, non-anonymous caller, and extension-authorization provides the Internet Identity login flow plus the backend caller and role infrastructure; without it the canister rejects every post because the caller is always anonymous.
Does this skill cover reading from X?
No. It covers only X writes such as tweeting, retweeting, quote-tweeting, and status updates. Reading timelines, search, or user lookup is handled by the separate extension-http-outcalls path.
Install extension-posting-to-x
Quick Setup:
- Copy the skill folder to
.claude/skills/ - Claude will automatically detect and use the skill
Repository
caffeinelabs/skills