Run your own robot for free
The software is free, and so are the APIs in the directory. Posting on X through its API is not free: it is pay-per-use. This guide covers the paths that cost $0 first, then shows how to keep an X robot as cheap as possible.
What's free, what isn't (checked 2026-10-10)
| Piece | Cost | Source |
|---|---|---|
| civicbot (CLI, SDK, skills, this site) | Free, MIT license | GitHub |
| Catalog skill APIs (Open-Meteo, NWS, USGS, NOAA, MBTA, TfL, Wikipedia…) | Free, no key. Each has fair-use limits and terms (Open-Meteo is free for non-commercial use) | directory |
Playground, civicbot chat, civicbot simulate | Free; never touches X | below |
| GitHub Actions to run your robot on a schedule | Free in public repos (standard runners). Private repos get 2,000 min/month on GitHub Free | GitHub docs |
| X API: reading your robot's mentions | Paid, per resource returned. $0.005 per Post read, or $0.001 as an “Owned Read” (see below) | docs.x.com pricing |
| X API: posting a reply | Paid: $0.010 per summoned reply, $0.015 for a regular post, and $0.20 if the post has a URL (civicbot replies never include links) | docs.x.com pricing |
| X starter credits | One-time per account: $20 when you save your first eligible card, plus a match of your first auto-recharge up to $50. A card is required. | docs.x.com free credits |
Bottom line: there is no $0 way to run a robot that replies on X through the API today. The X API has no free tier, so even a personal robot needs credits. Prices change, so check the Developer Console before you rely on these numbers.
Keeping X costs tiny
- Create the X developer app on the robot account itself. The pricing page says
GET /2/users/{id}/mentionsis billed as an Owned Read ($0.001 per resource) when{id}is the authenticated user and that user owns the developer app. - Reads are charged per resource returned, and the same Post is deduplicated within a 24-hour UTC day. An empty poll returns no resources.
- Replies only go to people who @mention the robot (“summoned”, $0.010). civicbot never puts links in replies.
- Rough example, our arithmetic and not an X quote: 100 questions a month ≈ 100 × ($0.001 read + $0.010 reply) ≈ $1.10/month.
- Set a spending limit in the Developer Console. Shadow mode (the default below) still reads mentions, so it costs reads but never pays for posts.
Option 1: $0, no install: the playground
Open the playground. Your browser calls free CORS-enabled APIs directly. Nothing is posted, and 311 reports are a dry run.
Option 2: $0, in your terminal
pip install civicbot
civicbot chat --free --city "Bloomington, IN" # interactive; type 'skills', 'help', 'quit'
civicbot chat -c "air quality" -c "holidays in PT" # one-shot questions
civicbot chat --offline -c "tides" # recorded sample data, no network
civicbot simulate --demo skills --offline --free # robots on a fake X: shows exactly what would be posted
Option 3: your real robot on X (pay-per-use X API), run free on GitHub Actions
- Make the robot's own X account, separate from yours (it counts toward your own 10-account limit), and mark it as automated, with you as the managing account (X automated-account labels).
- Create an X developer app on the robot account. Use OAuth 2.0 with the callback
http://127.0.0.1:8765/callbackand the scopestweet.read tweet.write users.read offline.access. Add credits and a spending limit. - Connect on your computer. The token is encrypted at rest and is never printed:
pip install "civicbot[secure]" export X_CLIENT_ID=... # from your app export X_CLIENT_SECRET=... # only if your app is "confidential" export CIVICBOT_TOKEN_KEY=$(python -c "from cryptography.fernet import Fernet;print(Fernet.generate_key().decode())") civicbot connect --listen --robot YOUR_ROBOT --owner YOUR_HANDLE --home-city "Your City, ST" --free civicbot run --robot YOUR_ROBOT # one poll, SHADOW: prints replies, posts nothing - Schedule it. Copy
examples/github-actions/civicbot-robot.yml
into
.github/workflows/in your own private repo. Add the secretsX_CLIENT_ID,X_CLIENT_SECRET,CIVICBOT_TOKEN_KEYandCIVICBOT_STATE_B64(tar czf - .civicbot | base64 -w0; the token inside is encrypted), plus the variableCIVICBOT_ROBOT. It polls every 30 minutes in shadow mode. Read the logs, and when you're happy set the variableCIVICBOT_POST=1.
Caveats
- Minutes: each run bills at least 1 minute. Every 30 minutes ≈ 1,440 runs/month, which fits a private repo's 2,000 free minutes. Every 15 minutes would not.
- Public repos: minutes are free, but GitHub disables scheduled workflows after 60 days without repository activity (docs). Workflow logs are public too, so stay in shadow mode or use a private repo.
- State (encrypted token and seen mentions) lives in the Actions cache. A cache unused for 7 days is evicted. If
that happens, the first run restores from
CIVICBOT_STATE_B64, and if the refresh token there is stale you will need to reconnect. Refresh tokens can rotate on use, so the workflow allows only one run at a time. - Schedules can be late under load. Treat this as a hobby robot, not an emergency service.
- Rules: follow X's automation rules. The robot answers only you and your allowlist, only when @mentioned, and only after your recorded consent. 311 reports stay a dry run in free mode.
Teach it more (still free)
Every skill in the directory that shows @yourrobot learn … is one message away.
To add an API that isn't in the catalog, write a skill spec (civicbot skill validate my.json) and open a pull
request so it can be reviewed and added. Free mode only learns reviewed catalog skills.