{"slug": "how-to-automate-scheduled-x-posts-with-codex-and-xurl", "title": "How to Automate Scheduled X Posts with Codex and xurl", "summary": "A developer built a scheduled X publishing workflow using OpenAI's Codex and the official X API command-line client, xurl. The system separates editorial decisions made by the AI agent from deterministic publishing actions, with a skill owning the write boundary and a scheduled task enforcing timing and editorial policy. The architecture includes four layers and was verified in August 2026.", "body_md": "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?\n\nI recently built a scheduled X publishing workflow with Codex and `xurl`\n\n, 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:\n\n`xurl`\n\n, which stores the credentials and communicates with the X API.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.\n\nIn this article, I’ll show you how to build the same architecture.\n\nX 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.\n\nBefore starting, you will need:\n\nYou 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.\n\nFor 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.\n\nInstall the official X Developer Platform CLI with Homebrew:\n\n```\nbrew install --cask xdevplatform/tap/xurl\n```\n\nThen verify that it is available:\n\n```\ncommand -v xurl\nxurl version\n```\n\nThe [ xurl project](https://github.com/xdevplatform/xurl) 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.\n\nOpen the [X Developer Console](https://developer.x.com/) and create an application for the account you intend to manage.\n\nConfigure user authentication with these general settings:\n\n| Setting | Value |\n|---|---|\n| App permissions | Read and write |\n| App type | Web App, Automated App, or Bot |\n| Callback URI | `http://localhost:8080/callback` |\n| Website URL | A valid website you control |\n| Environment | A production-capable API package |\n\nThe callback URI must match exactly. `xurl`\n\nuses `http://localhost:8080/callback`\n\nby default, although it can store a different redirect URI for an application if necessary.\n\nWhen 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.\n\nX exposes several credentials that look interchangeable but are not:\n\nSave 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.\n\nCredential 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:\n\n```\nread \"XURL_CLIENT_ID?Client ID: \"\nread -s \"XURL_CLIENT_SECRET?Client Secret: \"; echo\n\nxurl auth apps add my-x-app \\\n  --client-id \"$XURL_CLIENT_ID\" \\\n  --client-secret \"$XURL_CLIENT_SECRET\" \\\n  --redirect-uri http://localhost:8080/callback\n\nunset XURL_CLIENT_ID XURL_CLIENT_SECRET\n```\n\nNow authorize the intended account. Replace `my_handle`\n\nwith the handle without the `@`\n\ncharacter:\n\n```\nxurl auth oauth2 --app my-x-app my_handle\nxurl auth default my-x-app my_handle\n```\n\nThe OAuth command opens a browser. Sign in to the correct X account and approve the requested access.\n\nNext, verify the setup without publishing anything:\n\n```\nxurl auth status\nxurl whoami --username my_handle\nxurl posts my_handle -n 100 --username my_handle\n```\n\nThe `whoami`\n\nresult 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.\n\nAlso, never ask an agent to inspect or print anything under `~/.xurl/`\n\n. That directory contains authentication material. Avoid `xurl --verbose`\n\nin an agent session as well, because verbose request output can expose sensitive headers.\n\nCodex skills package repeatable instructions and optional executable logic. According to the [OpenAI skill documentation](https://learn.chatgpt.com/docs/build-skills), a skill is a directory with a required `SKILL.md`\n\nfile and optional scripts, references, assets, and interface metadata.\n\nFor this workflow, create a personal skill named something like `xurl-post`\n\n:\n\n```\nxurl-post/\n├── SKILL.md\n├── agents/\n│   └── openai.yaml\n└── scripts/\n    └── post.py\n```\n\nYou can invoke `$skill-creator`\n\nin Codex and describe what you want:\n\n```\nCreate a personal skill named xurl-post. Use the locally installed xurl CLI\nto publish finalized text and optional uploaded media from my_handle on X.\nSupport fully automated use, but verify the account before every write.\n```\n\nWhy use a script instead of putting the command directly in `SKILL.md`\n\n? Because this is exactly where deterministic behavior is valuable. Research and writing benefit from judgment. Account selection and argument construction do not.\n\nThe wrapper script should enforce the following rules:\n\n`xurl`\n\nexecutable.`xurl whoami --username my_handle`\n\nbefore every post.`xurl post TEXT --username my_handle`\n\n.`--media-id`\n\nvalues for media that has already been uploaded.`--dry-run`\n\nmode that checks identity and request construction without posting.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.\n\nYour 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.\n\nDo not publish “test 123” to a production account just to see whether the integration works.\n\nInstead, validate the skill with its dry-run mode or with a simulated `xurl`\n\nexecutable. Test at least these cases:\n\n`whoami`\n\nfails or returns malformed data.Once those tests pass, use one real, editorially valid post as the end-to-end production test.\n\nThe skill knows how to publish safely, but it should not decide what to publish. That belongs in the scheduled task’s saved prompt.\n\nA dependable prompt should tell Codex to perform the following sequence on every run:\n\n`$xurl-post`\n\nexactly once.The saved prompt must be self-contained. Do not rely on the agent remembering a policy you mentioned in a different conversation.\n\nHere is a reusable starting point:\n\n```\nOn every run, read the articles in this project to refresh the site's subjects\nand voice. Retrieve the full accessible post history for @my_handle before\nchoosing a topic. Find one timely story from an authoritative primary source\nthat fits the editorial policy below. Compare the source publication date with\nthe date of the underlying event or research. Reject exact duplicates and\nsemantically equivalent prior posts, even if their wording or URLs differ.\n\nWrite one concise, accurate, source-linked X post. Invoke $xurl-post exactly\nonce without requesting interactive confirmation. Report the source, exact\npublished text, duplicate check, and resulting post ID or URL. If history\nretrieval, research, or factual verification fails, skip the run and explain\nwhy. Never retry an ambiguous publishing result without first checking the\nnewest account history.\n\nEditorial policy:\n- [Your topic boundaries]\n- [Your source-quality requirements]\n- [Claims or language to avoid]\n- [When to label uncertainty]\n- [Any required disclosures]\n```\n\nIn Codex, create the scheduled task in plain language and attach it to the relevant project. For example:\n\n```\nCreate a scheduled task for this project that runs every day at 8:00 AM,\n1:00 PM, and 6:00 PM Central. Use the complete research, duplicate-checking,\neditorial, and publishing workflow in the prompt above.\n```\n\nUse the Codex Scheduled interface to review, edit, pause, resume, or remove the task. Background tasks can make file, network, and application changes according to their permissions, so keep the task’s sandbox and command rules as narrow as the workflow allows. OpenAI’s current [Scheduled tasks documentation](https://learn.chatgpt.com/docs/automations) is the best place to check the latest behavior and requirements.\n\nPreventing identical text is easy. Preventing repeated stories is harder.\n\nBefore researching or publishing, retrieve up to 100 recent posts:\n\n```\nxurl posts my_handle -n 100 --username my_handle\n```\n\nIf the API response provides a pagination token, continue through as much history as your access permits. Build a duplicate index from more than the post text:\n\nFor each candidate story, search history using distinctive title terms, the source domain, named entities, and the main claim. A new article about an old study is not necessarily a new story.\n\nMost importantly, make duplicate checking fail closed. If account history cannot be retrieved or checked reliably, the task should skip the run. Missing one scheduled post is much cheaper than eroding trust with duplicates.\n\nThis rule proved its value in my own health-news workflow. One run found a timely story, discovered that an equivalent post already existed, and skipped publishing. That was not a failed run; it was the system working correctly.\n\nBefore leaving the task unattended, test it in increasingly consequential stages:\n\n`https://x.com/my_handle/status/POST_ID`\n\n.Pause the task immediately if it drifts from the editorial policy, repeats stories, relies on weak sources, or overstates what a source supports.\n\nAutomation does not eliminate editorial responsibility. It merely moves that responsibility into the prompt, the skill boundary, and the monitoring process.\n\nReauthorize using the explicit handle, then reset the defaults:\n\n```\nxurl auth oauth2 --app my-x-app my_handle\nxurl auth default my-x-app my_handle\nxurl whoami --username my_handle\n```\n\nConfirm that the X application has **Read and write** permission and belongs to a usable production API package. If you changed its scopes, repeat OAuth so the new authorization receives the updated permissions.\n\nIf authentication succeeds but `whoami`\n\nreturns `client-forbidden`\n\nor `client-not-enrolled`\n\n, check the application’s package and production enrollment in the X Developer Console. The current [ xurl README](https://github.com/xdevplatform/xurl/blob/main/README.md) includes up-to-date enrollment troubleshooting.\n\nThe sandbox may block network access until a narrow permission is granted. Perform the first read-only and publishing tests interactively, then allow only the commands the scheduled workflow actually needs. Do not approve arbitrary shell or scripting access just to make unattended posting convenient.\n\nDo not retry immediately. Fetch the newest posts and compare the exact text, canonical source URL, and core claim. Retry only after confirming X did not create the post.\n\nCheck that:\n\n`xurl`\n\nis still available in the task environment.Pause the scheduled task before changing credentials, account settings, or the publishing skill.\n\nTo remove the integration completely, revoke the application in X and clear local `xurl`\n\nauthentication from your private Terminal:\n\n```\nxurl auth clear --all\n```\n\nIf a Client Secret, token, or authentication header ever appears in chat, logs, screenshots, or documentation, rotate or revoke it immediately. Deleting the copied text is not enough; the exposed credential must no longer be valid.\n\nThe best part of this architecture is not that an AI can post on a schedule. The best part is that each component has one clear job.\n\n`xurl`\n\nowns authentication. The Codex skill owns identity verification and the write operation. The scheduled prompt owns research and editorial judgment. Account history provides a feedback loop for duplicate prevention and ambiguous failures.\n\nThat separation turns a fragile cron job into a publishing workflow you can reason about. The agent is free to decide that there is nothing worth posting today—and the safest automation is often the one that knows when to do nothing.\n\n*This story was originally published at blog.designly.biz on August 16, 2026.*", "url": "https://wpnews.pro/news/how-to-automate-scheduled-x-posts-with-codex-and-xurl", "canonical_source": "https://dev.to/designly/how-to-automate-scheduled-x-posts-with-codex-and-xurl-4inb", "published_at": "2026-08-16 21:23:36+00:00", "updated_at": "2026-08-16 21:41:37.061802+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "artificial-intelligence"], "entities": ["Codex", "xurl", "X", "OpenAI"], "alternates": {"html": "https://wpnews.pro/news/how-to-automate-scheduled-x-posts-with-codex-and-xurl", "markdown": "https://wpnews.pro/news/how-to-automate-scheduled-x-posts-with-codex-and-xurl.md", "text": "https://wpnews.pro/news/how-to-automate-scheduled-x-posts-with-codex-and-xurl.txt", "jsonld": "https://wpnews.pro/news/how-to-automate-scheduled-x-posts-with-codex-and-xurl.jsonld"}}