Get started

X Plugin

An agent drafts it. You decide what goes out.

Overview

The X plugin is the governed connection between QuoxCORE and an X account. It does not write your posts for you: it takes a draft from wherever it came from, an agent, the quox x CLI or the dashboard, and holds it in the QuoxCORE inbox until a human decides. Nothing posts directly, by architecture, not by prompt.

The path is always the same: an agent or the quox x CLI drafts, and a HITL approval card lands in the inbox with the text, any image, and the remaining posting budget. Only when the owner taps Post does the plugin publish, with an OAuth 1.0a signed call to the X API.

Every publish decision is recorded as an AEE envelope, the open format Quox logs agent actions in, and witnessed under WARD, the protocol that makes that log tamper-evident. Both are described in the protocol overview. What went out and who approved it is on record, not remembered.

The write tools (post, thread, delete) are registered natively behind the approval gate. The connector bridge deliberately carries no write tools of its own, because the connector has no approval mechanism to put behind them.


Getting connected

There is no OAuth 2.0 connect flow yet. Setup is a vault credential: an OAuth 1.0a quad (API key, API key secret, access token, access token secret) created in the X Developer Portal and stored server-side.

1. Create the X application

In the X Developer Portal, create an application and generate the OAuth 1.0a keys and tokens. Two steps here have cost real setup time, so check both before generating anything:

i

Trap 1: attach the app to the Pay Per Use project. A detached app authenticates fine and then fails the moment it hits a paid endpoint. Confirm the app sits under the Pay Per Use project before doing anything else.

i

Trap 2: set Read and Write permission before you generate the access token pair. Tokens minted while the app is still read-only stay read-only forever. If you change the permission afterwards, you must regenerate the access token and secret; changing the setting alone does not upgrade tokens already issued.

2. Create the vault credential

bash
quox vault create --type twitter --name "X @handle" --set-default
# prompts for the four values: API key, API key secret, access token, access token secret
# never paste these into chat or a shared terminal

The credential is live-tested immediately with a signed call to api.x.com/2/users/me, so a bad key or a permission mismatch surfaces at setup, not on your first real post.

3. Or use the setup wizard

The /x view in the dashboard runs an XSetupWizard that walks through the same steps, traps included, and reports the same live verification result. quox x status shows credential health at any time afterwards.


Using it

The dashboard view

/x in QuoxCORE has five tabs: Compose (draft a post, reply or thread, attach up to four still images), Activity (what has been drafted, approved, discarded and published), Engagement (reactions, replies and reposts on published posts), Budget (usage against the daily and monthly caps), and Account health (credential status).

The Engagement tab spends real money, so it never fetches on its own. It reads through get_user_tweets only when you click Refresh, it never polls or fetches on mount, and the button states the cost of the click (about $0.05 for ten posts) before you make it.

The CLI

bash
quox x post "text"                       # draft a post -> HITL card
quox x post "text" --reply-to <tweet_id> # draft a reply
quox x post "text" --image <path>        # attach an image (up to 4)
quox x thread <file.md>                  # draft a thread from a markdown file
quox x delete <tweet_id>                 # governed delete (also a HITL card)
quox x status                            # budget usage + credential health
quox x media-root                        # print the org media root path

Thread file format: blank-line-separated blocks, one block per post; a line starting !image: inside a block attaches that image to that specific post.

Images and the media root

Images must live under the organisation's own media root, /var/lib/quox/x-media/<org_id>/ (quox x media-root prints yours). A path outside it is refused, with symlink escapes checked as well as the literal path. Honest gap: this directory is not auto-provisioned yet; if your first image post fails, create it by hand once.

The budget, and what refusal looks like

Every draft is checked against an org-scoped posting budget before it is created: 17 posts per rolling 24 hours, 500 per rolling 30 days, claimed atomically with a replay guard so approving the same card twice never posts twice. Reads carry their own budget, 200 per day.

When a draft would exceed the cap, the plugin refuses honestly rather than queuing it silently:

Daily X posting budget would be exceeded (17/17 already live, this needs 1 more).
Monthly X posting budget would be exceeded (500/500 already live, this needs 1 more).
Daily X read budget exhausted (200/200 reads in the last 24h; X read calls are pay-per-use, roughly $0.005 each). Try again later.

The approval card itself also shows the budget line before you decide, for example "this will be post N of 17 today", so the cost is visible before you tap Post, not just at the point of refusal.


What is shipped, what is Beta, and what is not built

This section mirrors STATUS_AND_LIMITS_X.md, the dashboard's own honest maturity map for this plugin, current as of 2026-09-12. If the two ever disagree, that file wins, not this page.

Stable: driven live, not just green in a test

  • Vault credential (OAuth 1.0a quad): live-tested against api.x.com/2/users/me, created via the CLI and resolved through the full credential chain.
  • Credential resolution (vault to bridge to tool): driven end to end.
  • Governed posting (x_post, x_thread, x_delete): 12 real posts published on @Quox_AI through draft, HITL card, approval, and an OAuth 1.0a-signed publish.
  • HITL enforcement on writes: enforced in code, not prompt text. Native tools file inbox cards, and the decide endpoint verifies approval authenticity against the auth service.
  • Posting budget (17/24h, 500/30d, atomic claims, replay guard): observed climbing from 2/17 to 12/17 across a live campaign; replay and over-budget refusal are covered by tests. The limits themselves are code constants today, pending a settings surface.
  • Image attachment (multipart upload, four-image cap, org media root): live image posts published; the org-scoped media root is symlink-safe and tested.
  • The quox x CLI (post, thread, delete, status): used for every post in the live campaign.
  • Evidence trail: an AEE envelope is emitted on every publish decision, witnessed via the collector store.

Beta: working, with named caveats

  • Read tools (get_tweet, get_user_tweets, search_recent, get_mentions): shipped with independently proven query-parameter signing and a 200-per-day read budget. get_mentions was driven against the live API on 2026-09-12 and returned a real mention. get_tweet, get_user_tweets and search_recent remain undriven. Note the parity gap below: there is no quox x read verb, so these are reachable from an agent or the dashboard, not the CLI.
  • The dashboard view (Compose, Activity, Engagement, Budget, Account health, plus the setup wizard): renders and gates correctly for a fresh organisation, but composing through to a published post via the UI itself has not yet been driven end to end.
  • Scheduling comes in two deliberately different lanes. The x-scheduled-post workflow template schedules drafting: each cron run files a fresh approval card, and a human tap still publishes (a live cron-fired run has not been driven yet). Separately, a human approver composing in the dashboard can choose approve and schedule: their tap at compose time IS the approval, and the publish fires at the chosen time through the same verified path, cancellable until it fires. Agent-initiated posts can never use that lane; they always wait for a human decision. A successful timed publish has not been driven live yet.
  • Plugin packaging (signed bundle, store descriptor, entitlement gating): the bundle is built and signed, and the licence gate is verified fail-closed in code, but that gate has not yet been proven against a genuinely unlicensed install.

Experimental: built, dark by default

  • The mentions poller: behind the X_INBOUND_POLL_ENABLED and X_INBOUND_POLL_ORGS flags, off by default, never run against live data. The failure-accounting, backoff and retirement triad is tested against stubs only.

Not built

  • Media beyond still images: no video, no animated GIFs, and no alt text. The tool layer sets no X media category, so animated GIFs are not supported even though .gif passes the file-extension check. Polls, quote posts and reply controls are not wired either.
  • OAuth 2.0, multi-account, per-account auto-post lanes: no live providers yet on the connect broker.
  • QuoxSignal listening unification: not started.

Known parity gap: no CLI read verbs

quox x covers post, thread, delete, status and media-root. There is no CLI verb for any of the four read tools, and quox tool manages the catalogue rather than executing tools, so reads are reachable only from an agent or the dashboard. Filed against the CLI rather than papered over here.


Pricing

The plugin itself is $10, one-time, at launch.

Posting still costs real money, because X's API is pay-per-use and that spend is on your own X account, not Quox's: roughly $0.015 per plain post, $0.20 per post that contains a link (which is also why a campaign link belongs in a self-reply rather than the main post), and $0.005 per read. The posting and read budgets above double as a spend guard against that cost, not only a rate limit.