How to Automate Scheduled X Posts with Codex and xurl
DEV Community

How to Automate Scheduled X Posts with Codex and xurl

Most social-media automation tutorials stop at โ€œcall the API on a cron job.โ€ That works, but it leaves the hard questions unanswered. Which account is the automation using? How does it avoid posting the same story twice? What happens when an API request times out after X has already accepted the post? And where should an AI agentโ€™s editorial freedom end? I recently built a scheduled X publishing workflow with Codex and xurl , the official command-line client for the X API. The result is not just a timer attached to an AI prompt. It is a small publishing system with four distinct layers: - An X developer application with read-and-write user authentication. - xurl , which stores the credentials and communicates with the X API. - A fixed-account Codex skill that verifies the identity before every write. - A Codex scheduled task that researches, checks history, drafts, and publishes. That separation is the important part. Codex can make editorial decisions, but it cannot casually choose an account or improvise the publishing command. The skill owns the deterministic write boundary, while the scheduled task owns timing and editorial policy. In this article, Iโ€™ll show you how to build the same architecture. X developer settings, API packages, Codex features, and command-line options can change. The workflow below was verified in August 2026, but you should check the current upstream documentation before using it in production. What You Will Need Before starting, you will need: - Codex on a Mac with access to Scheduled tasks. - An X developer account and an application with read-and-write permissions. - Homebrew. - A dedicated or clearly identified X account for the automation. - A local project containing the source material or editorial context the agent should use. You should also decide what the automation is allowed to publish before you give it access to an account. A good editorial policy is specific enough to reject a story, not merely broad enough to describe a topic. For example, I built one version of this workflow for a health-news account. Its policy covered metabolic health, nutrition research, and evidence quality. It also required the agent to distinguish association from causation, label animal studies and preprints, avoid personalized medical advice, and prefer primary sources. Those rules mattered just as much as the code. Install xurl Install the official X Developer Platform CLI with Homebrew: brew install --cask xdevplatform/tap/xurl Then verify that it is available: command -v xurl xurl version The xurl project supports OAuth 2.0 user authentication, multiple applications and accounts, shortcuts for common X actions, media uploads, and raw X API requests. Most importantly for this workflow, it gives us simple commands for identifying the authenticated user, reading account history, and creating a post. Create an X Developer Application Open the X Developer Console and create an application for the account you intend to manage. Configure user authentication with these general settings: | Setting | Value | |---|---| | App permissions | Read and write | | App type | Web App, Automated App, or Bot | | Callback URI | http://localhost:8080/callback | | Website URL | A valid website you control | | Environment | A production-capable API package | The callback URI must match exactly. xurl uses http://localhost:8080/callback by default, although it can store a different redirect URI for an application if necessary. When X asks how you will use its data, describe the real first-party workflow. A suitable statement might explain that the application will create original or scheduled posts, read the accountโ€™s own history to prevent duplicates, and retain only minimal operational data such as post IDs, source URLs, timestamps, and publishing status. Know Which Credential You Need X exposes several credentials that look interchangeable but are not: - An OAuth 2.0 Client ID and Client Secret are used for the user authorization flow in this tutorial. - A Consumer Key and Consumer Secret belong to OAuth 1.0a. - A Bearer Token is commonly used for app-only authentication and is not a substitute for the user context needed to publish as your account. Save the OAuth 2.0 Client ID and Client Secret privately. Never paste them into a Codex conversation, a Markdown file, a screenshot, or your source repository. Authorize the Account Locally Credential setup should happen in a private Terminal controlled by you, not inside an agent session. This zsh pattern prevents the literal secret from being recorded in shell history: read "XURL_CLIENT_ID?Client ID: " read -s "XURL_CLIENT_SECRET?Client Secret: "; echo xurl auth apps add my-x-app \ --client-id "$XURL_CLIENT_ID" \ --client-secret "$XURL_CLIENT_SECRET" \ --redirect-uri http://localhost:8080/callback unset XURL_CLIENT_ID XURL_CLIENT_SECRET Now authorize the intended account. Replace my_handle with the handle without the @ character: xurl auth oauth2 --app my-x-app my_handle xurl auth default my-x-app my_handle The OAuth command opens a browser. Sign in to the correct X account and approve the requested access. Next, verify the setup without publishing anything: xurl auth status xurl whoami --username my_handle xurl posts my_handle -n 100 --username my_handle The whoami result must contain the exact account you expect. If it does not, stop. Do not โ€œtestโ€ the configuration by sending a post from an uncertain identity. Also, never ask an agent to inspect or print anything under ~/.xurl/ . That directory contains authentication material. Avoid xurl --verbose in an agent session as well, because verbose request output can expose sensitive headers. Put a Fixed-Account Skill in Front of the API Codex skills package repeatable instructions and optional executable logic. According to the OpenAI skill documentation, a skill is a directory with a required SKILL.md file and optional scripts, references, assets, and interface metadata. For this workflow, create a personal skill named something like xurl-post : xurl-post/ โ”œโ”€โ”€ SKILL.md โ”œโ”€โ”€ agents/ โ”‚ โ””โ”€โ”€ openai.yaml โ””โ”€โ”€ scripts/ โ””โ”€โ”€ post.py You can invoke $skill-creator in Codex and describe what you want: Create a personal skill named xurl-post. Use the locally installed xurl CLI to publish finalized text and optional uploaded media from my_handle on X. Support fully automated use, but verify the account before every write. Why use a script instead of putting the command directly in SKILL.md ? Because this is exactly where deterministic behavior is valuable. Research and writing benefit from judgment. Account selection and argument construction do not. The wrapper script should enforce the following rules: - Resolve the local xurl executable. - Run xurl whoami --username my_handle before every post. - Parse the returned JSON and require an exact username match. - Refuse the write if authentication or identity verification fails. - Pass the finished post as a direct process argument, never through shell interpolation. - Publish with xurl post TEXT --username my_handle . - Support repeated --media-id values for media that has already been uploaded. - Provide a --dry-run mode that checks identity and request construction without posting. - Never blindly retry a failed or interrupted publish. The final rule deserves emphasis. If a request reaches X but the response is lost, the command may look like it failed even though the post exists. An automatic retry can therefore create a duplicate. After an ambiguous result, read the newest account history before doing anything else. Your skill instructions should also define authorization clearly. A request to publish, post, send, or automate finalized copy can authorize a write. A request to draft, revise, review, or preview should not. Test the Publishing Boundary Without Posting Garbage Do not publish โ€œtest 123โ€ to a production account just to see whether the integration works. Instead, validate the skill with its dry-run mode or with a simulated xurl executable. Test at least these cases: - The expected account is authenticated and the request is constructed correctly. - A different account is authenticated and the script refuses to continue. - whoami fails or returns malformed data. - The post contains quotation marks, apostrophes, URLs, emoji, and line breaks. - One or more media IDs are passed as separate arguments. Once those tests pass, use one real, editorially valid post as the end-to-end production test. Give the Scheduled Task a Complete Editorial Workflow The skill knows how to publish safely, but it should not decide what to publish. That belongs in the scheduled taskโ€™s saved prompt. A dependable prompt should tell Codex to perform the following sequence on every run: - Read the projectโ€™s current articles or other source material to refresh its understanding of the siteโ€™s subjects and voice. - Retrieve the X accountโ€™s accessible post history. - Search for recent stories from authoritative, preferably primary, sources. - Compare the publication date with the date of the underlying study, release, or event. - Reject exact and semantic duplicates. - Draft one concise, source-linked post that accurately represents the evidence. - Invoke $xurl-post exactly once. - Report the source, final text, history check, and returned post ID or URL. - Skip the run if research, history retrieval, or factual verification fails. The saved prompt must be self-contained. Do not rely on the agent remembering a policy you mentioned in a different conversation. Here is a reusable starting point: On every run, read the articles in this project to refresh the site's subjects and voice. Retrieve the full accessible post history for @my_handle before choosing a topic. Find one timely story from an authoritative primary source that fits the editorial policy below. Compare the source publication date with the date of the underlying event or research. Reject exact duplicates and semantically equivalent prior p

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.