X posting agent

One measured finding a day becomes an X post. The API posts it; nobody types.

An X account that posts once a week reads as abandoned, and one that posts generic advice reads as a bot. What holds up is a steady run of specific, measured observations, one a day, and writing that takes an hour nobody has once the first week’s enthusiasm is gone.

Running on our own company since Oct 14, 2026 · X · Risk: Medium. Everything on this page is public; there is nothing to sign in for.

Goes inThe first pending row of a topic calendar: one measured finding from our AI-visibility reports, an optional angle, and the form (short post or thread)
Comes outOne post or one thread of four to six segments on the account’s timeline, and one entry in the registry file this log is built from
Human stepNobody, on a normal day. A person writes the calendar rows and decides what happens to a thread X refused partway; nothing is retried on its own
Runs onA machine you control, once a day at a random minute of a morning window, with no browser in the loop

Tasks and outputs

What it takes on

Take the row

Reads the calendar top to bottom and takes the first row still pending: the finding, the angle, the form. Never by date, never out of order.

One row

Write and lint

Writes the post from the finding to the voice guide, in a session with no way to post, then runs lint: segment count, length, links, brand, banned words, the row’s day and form.

One accepted draft

Post and record

Posts through the X API as the calendar’s account, writes the registry entry after the first 201, flips the row, commits both files and triggers the deploy.

Post + registry entry

Who it is for: Founders and small teams who have real findings to share (measurements, experiments, numbers from their own work) and want them on X every day without a person at the keyboard, and without the browser automation X suspends accounts for.

How we use it: We built it for our own new X account in October 2026: every day, at a random minute of the morning, it takes the next row of a calendar of findings from the free AI-visibility reports we wrote for fifty startups, writes a short post or a thread from it, checks the draft by rule, and posts it through the X API. No link and no brand in any post for the first two weeks; the clients the findings come from are never named. The registry behind the run log records every post that went out.

Workflows/x-post/voice.mdRules the post is written to

What a post looks like

01The first line is a number or a counter-intuitive result. Never a definition, never “a thread on”, never a preview.

02A short post is one segment. A thread is four to six: a hook, three or four segments with one number or one mechanism each, a last one with the lesson or the open question.

03Each segment 260 characters or fewer (lint allows 280). No link, no domain, no “link in bio”.

04No brand before 2026-10-26. No client name ever: the company in a finding is “a startup”, “one company”, “a vendor”.

05None of the banned words, no em or en dash, no hashtag, no call to action, at most one emoji. Every number is in the calendar row or in a report file the draft names; lint reads those files and refuses a number it cannot find.

06A draft that fails lint twice is not posted; the calendar is never edited to make one pass.

Read from the voice guideOne a day, at a random minute

The rules the agent’s output is written to, from the file named above. This site prints no example output; what the agent has shipped is in its run log.

Workflow

How a run goes, step by step

Pick a step to see what goes in, what comes out, and where a person is involved.

Step 1 of 6

Take the first pending row

Once a day, at a random minute inside a morning window, the wrapper brings its checkout to the latest main, checks that the posting account’s credentials are there, and reads the calendar for the first row still pending. An empty calendar ends the run before any session starts, with a line in the log on the machine and an exit code the watchdog reports.

Goes in

Workflows/x-post/geo-topics.md

Comes out

One row: day, finding, angle, form

Where a person steps in

Nobody. When the calendar is empty, a person adds rows; the next run takes the first.

Step 2 of 6

Write the draft

A session starts with the row’s day and form, reads the finding and the voice guide, and writes one short post or one thread. The session can read the repository and run the calendar reader and lint, and nothing else: it holds no credentials and cannot run the posting script. The first line is the number or the result; each thread segment carries one point; no link, no brand before the date in the guide, no client name.

Goes in

The row and Workflows/x-post/voice.md

Comes out

A draft file: day, form, segments

Where a person steps in

Nobody. A session that writes nothing within ten minutes is stopped and the run ends with no post.

Step 3 of 6

Lint, twice

The session runs lint on its draft and, when it passes, lint copies the draft to the file the posting script takes. The wrapper runs the same lint again on that file before posting. The rules are form, not taste: segment count for the form, 280 characters a segment as X counts them, links, the brand rule, the banned words and dashes, and that the draft is for the row that is due.

Goes in

The draft

Comes out

An accepted draft, or the run ends

Where a person steps in

Nobody. A draft that fails twice ends the run with the errors in the log; the row stays pending for the next day.

Step 4 of 6

Post through the API

The posting script signs each request with the posting account’s OAuth 1.0a credentials and sends it: one request for a short post, one per segment for a thread, each a reply to the one before, two seconds apart. It expects 201 and the post id back. A refused request stops the loop: the segments already posted stay, nothing is retried, and the output names the cause (token, credits, duplicate text, rate limit).

Goes in

The accepted draft and the credentials file

Comes out

Post ids, or a named refusal

Where a person steps in

When a thread stops partway: a person posts the rest by hand or deletes the live segments. The run does not wait.

Step 5 of 6

Record and flip the row

After the first segment went out, the script writes one entry to the registry, keyed by calendar day: the ids, the first post’s link, date and time, the form, the segments as posted, and ok or partial. Then it flips the calendar row to posted with the link. A run that posted nothing writes neither.

Goes in

The ids and the draft

Comes out

One entry in web/content/x-posts.json and one posted row

Where a person steps in

Nobody. The registry is the record; a person never edits it to make a run pass.

Step 6 of 6

Commit and deploy

The wrapper commits exactly the calendar and the registry, pushes, and triggers the deploy that builds this log from the registry. A partial entry shows here as a record that needs a person; a run that ended before posting shows as a gap, with its reason in the log on the machine.

Goes in

The two changed files

Comes out

This record

Where a person steps in

When the push fails: a person pushes. The files are already written locally.

Before you start

What you’ll need to bring

Company material

Findings worth a post: measured results with numbers, one per calendar row, that stand without the name of whoever they were measured on. Ours come from the free AI-visibility reports we wrote for fifty startups.

Source material

The topic calendar: a markdown table a person fills, one row a day, with the finding, an optional angle and the form. The agent reads it top to bottom and flips rows; it never writes findings.

Platform account

An X developer account with pay-per-use credits and an app with write permission, and the posting account authorized once against it through X’s PIN flow. The two can be the same account; ours are not.

Run environment

A machine that is on in the morning: Node.js for the three scripts, an agent runner that follows a written workflow for the writing step, and a scheduler. We use Claude Code under Windows Task Scheduler. No browser is needed.

Run log

Recent runs, as they happened

The full log is public and read-only. It holds every run on record, including the ones that stopped to wait for a person.

View the full run log

Guides and files

Set it up yourself

The setup guide, and the files the agent is built from. You run it in your own environment, with your own accounts.

Open · no account neededA Claude Code workflow (markdown instructions), a voice guide, a topic calendar, three Node scripts (the calendar reader, lint, and the posting script with the OAuth signing it shares with the X comment agent) and the wrapper the scheduler runs. Not packaged for public download yet — the setup guide below describes what they do; the managed tier runs it for you today.
Setup guide
  1. 01

    Runtime

    • Node.js 20 or later. The three scripts have no dependencies; the signing is a hundred lines of HMAC-SHA1.
    • A scheduler that starts the wrapper once a day at a random minute inside a morning window, and an agent runner that follows the written workflow for the writing step — ours is Claude Code, started by Windows Task Scheduler on the founder’s machine.
  2. 02

    Browser setup

    • None. The post goes out through the API; nothing in this agent opens a browser. That is also why it is allowed: X lists browser automation as grounds for permanent suspension and permits automated original posts through the API.
  3. 03

    Account setup

    • An X developer account with pay-per-use credits and an app with read and write permission. Posting costs $0.015 a request at 2026 prices, $0.20 when the post carries a URL.
    • The posting account, authorized once against that app through X’s PIN flow; its four OAuth 1.0a strings do not expire, so there is no token to refresh on an unattended machine. Ours is a separate account from the developer account.
  4. 04

    Configuration

    • The topic calendar: one row per day with a measured finding, an optional angle, the form (short or thread), and the status the script flips. The handle that posts is a line above the table.
    • The voice guide: the hook rule, the one-point-per-segment rule, the length, the banned words, the no-link rule and the date before which no brand is named.
    • The lint rules, as constants at the top of the lint script: change a rule there, not the flow.
  5. 05

    First run

    • Run the wrapper in dry-run mode two or three times and read the drafts; if they are correct but dull, the calendar’s findings are not specific enough. Fix the calendar, not the prompt.
    • Post the first one by hand with the posting script, check it on the account’s timeline, check the registry entry and the calendar row, then register the schedule.
Files · 8

x-post.md

Workflow · Markdown. The steps: the row, the voice guide, the draft, the checklist, lint, post, commit and deploy.

Workflow

voice.md

Voice guide · Markdown. The hook rule, one point per segment, the length, the banned words, the no-link and no-brand rules, the checklist.

Voice guide

geo-topics.md

Calendar · Markdown. One row per day: the finding, the angle, the form, the status the script flips, the date and the link. The handle that posts is a line above the table.

Calendar

calendar.mjs

Script · Node. Reads the calendar: the first pending row for the wrapper and lint, and the flip to posted for the posting script.

Script

lint.mjs

Script · Node. The deterministic checks on a draft, and the copy of an accepted draft to the file the posting script takes.

Script

post.mjs

Script · Node. Posts the accepted draft through the X API (OAuth 1.0a signing shared with the X comment agent), writes the registry entry, flips the row. Never retries.

Script

run-x-post.ps1

Scheduler · PowerShell. The daily run: the checkout, the row, the writing session, lint, post, one commit of the two files, the deploy trigger.

Scheduler

x-posts.json

Registry · JSON. One entry per post or thread published, keyed by calendar day. The file this log is built from.

Registry

Not packaged for public download yet. The guide on the left describes what each one does, step by step, so you can rebuild the setup; the Hosted and Fully managed tiers run them for you today.

Rather have us run it?

Hosted: your accounts in a cloud browser we run, and you review what goes out. Fully managed: we set the strategy and run the agents.

Good to know

Where it stops and asks for you

  • The calendar has no pending row. The run ends before any session, with a line in the log and an exit code the watchdog emails about. A person adds rows.
  • The posting account’s credentials file is missing. The run ends before any session. A person runs the one-time PIN authorization again.
  • The session did not write a draft within ten minutes. The session is stopped; nothing is posted; the row stays pending for the next day.
  • The draft failed lint twice. Nothing is posted; the errors are in the log on the machine; the row stays pending. A finding that keeps producing failing drafts is rewritten in the calendar by a person.
  • X refused the first request. Nothing is posted and nothing is written; the output says why: 401 token, 402 credits, 403 duplicate text or permission, 429 rate limit.
  • X refused a later segment of a thread. The segments before it are live and recorded as partial; the record here needs a person, who posts the rest by hand or deletes the live ones. Nothing is retried.
  • The push failed. The commit stays local and a person pushes; the registry entry and the calendar flip are already written.

Risk notice

What to watch for

  • X’s developer rules shape this agent: original posts through the paid API, no browser, no automated replies. Keep it to posting; replies are the X comment agent’s, and a person posts those.
  • Nobody reads a post before it goes out. The controls are the calendar (a person writes the findings), the voice guide and lint; a post can still be correct and dull. If the drafts are not good enough after two weeks, the fallback is a text column in the calendar: a person writes the posts, the agent only posts them.
  • Posting costs money, a dollar or two a month at one post a day; a thread is one request per segment. The developer account’s credits are shared with the X comment agent’s reads. Set a monthly limit in the developer console.
  • A new account gets little reach for weeks. Low numbers in the first month are not a signal to post more.

FAQ

Questions about this agent

Why the API and not the browser, like the LinkedIn agent?

X has an API that allows automated original posts and prices them at cents; LinkedIn does not. X also names browser automation as a permanent-suspension offence. The API path is cheaper, more stable, and the one X permits.

Can the writing session post something it should not?

No. The session that writes has no credentials and cannot run the posting script; the worst it can do is write a bad draft, and lint reads the draft before anything is sent. The posting script is run by the wrapper, or by a person.

A thread stopped partway.

The segments that went out are recorded as a partial entry and the record here is marked as needing a person. Post the rest by hand from the registry’s text, or delete the live segments; the agent does not retry a refused request.

The calendar ran out.

The run stops before starting a session, writes a line to its log on the machine, and exits with a code the watchdog emails about. Add rows; the next run takes the first new one.