Skip to main content

Reddit listings + Citedy Agent API autopilot (no scout credits). Optional interactive setup.

Project description

citedy-reddit-writer

PyPI version Python 3.10+ License: MIT

Turn relevant Reddit threads into Citedy articles — automatically, on a schedule, without spending scout/reddit credits on each poll.

This small CLI watches the subreddits you care about, keeps a local dedupe ledger, and calls Citedy’s Agent API POST /api/agent/autopilot with source_urls pointing at real Reddit posts. You choose filters, daily caps, and whether Citedy should auto-publish or stop at a draft.

Links
Source github.com/citedy/citedy-reddit-writer
Package pypi.org/project/citedy-reddit-writer
Citedy citedy.com — Agent API key (citedy_agent_…)

Install (fastest)

Recommended — isolated CLI (no virtualenv to remember):

pipx install citedy-reddit-writer
citedy-reddit-setup   # first time: writes config.yaml + .env
citedy-reddit-run --config config.yaml

Or with pip (use a venv in production):

pip install citedy-reddit-writer

Check the install:

citedy-reddit-run --help
citedy-reddit-setup --help

Minimal run (API key only)

From v0.1.1, you can skip config.yaml if the bundled defaults are fine (sample subreddits SEO, bigseo, filters, caps — see citedy_reddit_writer/default_config.yaml in the repo). Set CITEDY_AGENT_API_KEY (and optionally CITEDY_BASE_URL if not using https://www.citedy.com), load .env if you use one, then:

set -a && source .env && set +a
citedy-reddit-run --dry-run
citedy-reddit-run

If config.yaml exists in the current directory, it wins. If there is no config.yaml but config.example.yaml is present, that file is used. Otherwise the packaged defaults apply and relative paths (e.g. state file) resolve from the current working directory.

Upgrade later:

pipx upgrade citedy-reddit-writer
# or: pip install -U citedy-reddit-writer

Reddit transport fallback

Reddit may intermittently block one HTTP stack while allowing another for the exact same public listing URL. The default reddit.transport: auto mode tries httpx first and automatically retries via Python’s stdlib urllib when Reddit returns a block page or a transport-specific fetch failure.

You can pin the behavior if you need to debug or force one path:

reddit:
  transport: "auto" # auto | httpx | urllib

Or override it at runtime:

export CITEDY_REDDIT_TRANSPORT=urllib

First run in two minutes

  1. Install (see above).

  2. Run citedy-reddit-setup — it asks for your Citedy base URL, Agent API key, subreddits, keyword filters, limits, and auto_publish. It writes config.yaml and .env (keep the key in .env, not in git).

  3. Load env and run once:

    set -a && source .env && set +a
    citedy-reddit-run --config config.yaml
    

Dry-run (no API calls, no state file updates — safe to try anytime):

citedy-reddit-run --config config.yaml --dry-run

Get your Agent API key

This CLI talks to Citedy’s Agent API using a key that looks like citedy_agent_…. Put it in .env as CITEDY_AGENT_API_KEY (the setup wizard does this for you).

Option A — Dashboard (fastest for most people)

  1. Sign in at citedy.com.

  2. Open Settings → Team & API:
    citedy.com/dashboard/settings?section=team

  3. Create or copy your Agent API key and paste it when citedy-reddit-setup asks — or add it manually to .env:

    CITEDY_AGENT_API_KEY=citedy_agent_your_key_here
    

Option B — Register an agent via API (one-time, email approval)

curl -sS -X POST "https://www.citedy.com/api/agent/register" \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","name":"My Agent"}'

Open the approval link in the email you receive. The JSON may return a field named api_key — put that value in .env as CITEDY_AGENT_API_KEY=…. This is the same env name this CLI, citedy-reddit-setup, and Citedy MCP expect for the Agent API (Bearer token).

Sanity check

curl -sS "https://www.citedy.com/api/agent/health" \
  -H "Authorization: Bearer $CITEDY_AGENT_API_KEY"

Real-world stories (human flow)

These are not magic prompts into Reddit itself — the tool fetches public subreddit listings locally, picks a post that matches your filters, then sends one Reddit URL to Citedy autopilot. The “human” part is how you drive it from an IDE or another agent.

Overview — three ways to drive the same CLI

flowchart TB
  subgraph S1["Story 1: IDE"]
    A1[You chat in Cursor / Claude / Codex]
    A2[Agent runs CLI with skill]
    A1 --> A2
  end

  subgraph S2["Story 2: Agent + shell"]
    B1[OpenClaw or headless agent]
    B2[pipx install and setup]
    B1 --> B2
  end

  subgraph S3["Story 3: Schedule"]
    C1[cron or systemd]
    C1 --> C2[citedy-reddit-run]
  end

  A2 --> CLI[citedy-reddit-run]
  B2 --> CLI
  C2 --> CLI
  CLI --> OUT[Reddit URL to Citedy autopilot then blog if auto_publish]

Story 1 — You’re in Cursor, Claude Code, or Codex

flowchart TB
  U[You type plain language in chat]
  U --> SK[Skill loads CLI and .env path rules]
  SK --> E[source .env or load CITEDY_AGENT_API_KEY]
  E --> DR[dry-run: log topic and Reddit URL only]
  DR --> Q{Good angle?}
  Q -->|Adjust config| U
  Q -->|Yes| RR[Real run: citedy-reddit-run]
  RR --> AP[Citedy autopilot]
  AP --> BL[Blog post when auto_publish is true]
  1. Install (once): pipx install citedy-reddit-writer (or pip install …).
  2. In a terminal (or ask the agent to run it): citedy-reddit-setup — point at r/SEO (or your niches), add keywords like agency, growth, ranking, set auto_publish: true if you want live posts on your Citedy blog.
  3. You type in chat, in plain language:
    “Run citedy-reddit-run --config config.yaml --dry-run and tell me which Reddit thread you would send to Citedy.”
    The skill / agent should cd into the project folder, source .env, then run the command. You see no article yet — only log lines like DRY_RUN: would call autopilot … with a topic + URL.
  4. When it looks right:
    “Same thing but for real — one article, env loaded.”
    citedy-reddit-run --config config.yaml
  5. If autopilot succeeds and auto_publish is on, a post can appear on your blog on citedy.com within the time your plan allows (async jobs may take minutes).

Why use the skill? So the agent knows the flags, your config.yaml path, and never pastes your key into chat — only reads .env.

Story 2 — OpenClaw, Claude Code on a headless box, or “any agent with a shell”

flowchart LR
  AG[Agent or you in terminal]
  AG --> PX[pipx install citedy-reddit-writer]
  PX --> SU[citedy-reddit-setup]
  SU --> OP[Optional: add SKILL.md to agent]
  OP --> DR[dry-run]
  DR --> AP[You approve]
  AP --> RR[Real run]
  RR --> CY[Citedy autopilot and blog]
  1. You (or the agent) run:
    pipx install citedy-reddit-writer
  2. You say:
    “After install, run citedy-reddit-setup and configure for [topic]. Then dry-run once.”
  3. Same pattern: dry-run first (safe), then real run when you approve.
    You can paste the skill text from this repo (.claude/skills/… / .cursor/skills/…) into the product’s skill store so the agent doesn’t guess the CLI.

Story 3 — Scheduled, hands-off

flowchart LR
  T[cron or systemd timer]
  T --> R[citedy-reddit-run]
  R --> ENV[Environment has CITEDY_AGENT_API_KEY]
  ENV --> CY[Citedy autopilot]
  CY --> BL[New post when filters match and cap allows]

You don’t talk to the IDE for each post: cron or systemd runs citedy-reddit-run every few hours. The “conversation” happened once when you wrote config.yaml.


Case study: from “what’s hot on r/SEO?” to a live article

Setup: Subreddit r/SEO, filters around agency growth / SEO industry / ranking, reasonable min_score and max_age_hours, articles_per_run: 1, auto_publish: true.

  1. Dry-run — You (or your agent) run:
    citedy-reddit-run --config config.yaml --dry-run
    Logs show which thread would be used as source_urls and the synthetic topic string — no Citedy write, no state update.

  2. Real run — Same command without --dry-run, with CITEDY_AGENT_API_KEY in the environment. The CLI calls POST /api/agent/autopilot with that Reddit URL; Citedy generates the article and, with auto_publish, can publish to your site.

  3. Outcome (real example) — One such production-style run produced a long-form guide that went live on the Citedy blog, e.g.
    SEO Agency Growth Guide: Build Your Agency Through SEO Only
    Your URLs will differ by account, topic, and filters; this link illustrates the end state: a public post you can share, not a file stuck on your laptop.

Takeaway: Install → key from Team & API (or register flow) → setup wizarddry-run (human checks the angle) → one real run → optional live blog post on your Citedy-hosted content.


How it works

High-level flow:

flowchart LR
  subgraph Reddit["Reddit (public .json)"]
    R[Listings per subreddit]
  end

  subgraph Local["Your machine"]
    F[Keyword and score filters]
    D[State file dedupe]
    C[Per-run and daily caps]
  end

  subgraph CitedyAPI["Citedy Agent API"]
    A["POST /autopilot + source_urls"]
    P{200 sync or 202 async}
    Q[Poll job until done]
  end

  R --> F --> D --> C --> A --> P --> Q

Step by step

  1. Fetch recent posts from each configured subreddit using Reddit’s public listing endpoints (not the paid “scout” Reddit scout inside Citedy — so you don’t burn scout credits on every scheduler tick). In the default auto mode the CLI will retry with an alternate HTTP transport if Reddit blocks the first attempt.
  2. Filter by include/exclude keywords, minimum score, and max post age.
  3. Dedupe using a local JSON state file (post IDs and title hashes), optionally cross-checking recent article titles from your Citedy account so you don’t repeat topics.
  4. Respect caps: articles_per_run and max_articles_per_day prevent bursts.
  5. For each chosen post, build a topic from your template and call autopilot with source_urls: [post.url] (and your auto_publish, language, size, etc.).
  6. If the API returns 202, the CLI polls the job until it finishes or times out (configurable). On success, state is updated so the same post is not picked again.

You can run this manually, from cron, or via systemd timer (see crontab.example and systemd/).


Why this exists

  • Automation: Same story as “I want a steady pipeline from social signals to published content,” without babysitting the UI.
  • Cost-aware: Polling Reddit uses public listings + your own rate limits; it does not use Citedy’s scout/reddit quota for those fetches.
  • Control: You own config.yaml — subreddits, filters, caps, and whether articles go live with auto_publish.

Configuration

What How
Interactive citedy-reddit-setupconfig.yaml + .env
Reference config.example.yaml (all keys explained in comments)
Env vars CITEDY_AGENT_API_KEY (required), CITEDY_REDDIT_CONFIG (config path), optional CITEDY_BASE_URL, CITEDY_ALERT_WEBHOOK_URL, DRY_RUN

Paths like dedupe.state_path are resolved relative to the config file’s directory.


Scheduling

  • Cron: see crontab.example.
  • systemd: systemd/citedy-reddit-writer.service + citedy-reddit-writer.timer.

Ensure the service environment loads .env or injects CITEDY_AGENT_API_KEY securely.


Agent skills (Claude Code, Cursor, Codex)

Environment Skill / command
Claude Code .claude/skills/citedy-reddit-writer/SKILL.md + slash command /citedy-reddit-writer (.claude/commands/citedy-reddit-writer.md)
Cursor In the saas-blog monorepo: .cursor/skills/citedy-reddit-writer/SKILL.md
Codex In the saas-blog monorepo: .codex/skills/citedy-reddit-writer/SKILL.md

This repo includes .claude/ and .cursor/skills/ for a standalone clone. For Codex-only setups, copy .codex/skills/... from the monorepo if needed.

saas-blog monorepo: one command from the Next.js repo root

If CITEDY_AGENT_API_KEY (and optional vars) live in the monorepo .env and config.yaml is under citedy-reddit-writer/ (after citedy-reddit-setup), run:

npm run citedy-reddit-writer -- --dry-run   # safe: no API writes
npm run citedy-reddit-writer                # real run

This uses run-with-env.sh: loads ../.env then citedy-reddit-writer/.env (package overrides parent). Uses citedy-reddit-writer/.venv/bin/citedy-reddit-run when present; otherwise citedy-reddit-run on PATH. Install once: cd citedy-reddit-writer && python3 -m venv .venv && .venv/bin/pip install -e ..


Development install (from a git clone)

git clone https://github.com/citedy/citedy-reddit-writer.git
cd citedy-reddit-writer
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
citedy-reddit-setup

Requirements & etiquette

  • Python 3.10+
  • A valid Citedy Agent API key.
  • Respect Reddit Data API terms: set a honest user_agent, don’t hammer endpoints, stay within reasonable automation.

Security

  • Do not commit .env or a config.yaml that embeds agent_api_key. Prefer an empty key in YAML and load secrets from the environment.
  • Treat config.yaml and state files as sensitive if they reveal your editorial strategy.

For maintainers

Open-source users only need this repo and PyPI. Releasing (monorepo → citedy/citedy-reddit-writer, subtree, PyPI tags) is documented inside the private Citedy monorepo at docs/citedy-reddit-writer/DEPLOYMENT.md — it is intentionally not shipped here.


License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

citedy_reddit_writer-0.1.2.tar.gz (22.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

citedy_reddit_writer-0.1.2-py3-none-any.whl (23.2 kB view details)

Uploaded Python 3

File details

Details for the file citedy_reddit_writer-0.1.2.tar.gz.

File metadata

  • Download URL: citedy_reddit_writer-0.1.2.tar.gz
  • Upload date:
  • Size: 22.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for citedy_reddit_writer-0.1.2.tar.gz
Algorithm Hash digest
SHA256 b79a41e67af1b1467c6e5a0d3cae318c2bbb345c1646abad90252784e28f4fd5
MD5 5548b71e25bc4d25aa9eb791dcb31324
BLAKE2b-256 424ed9889bbc6f9c40074f2ba6d3d011f9abb2916d5319f17e6310cbe32ab48c

See more details on using hashes here.

Provenance

The following attestation bundles were made for citedy_reddit_writer-0.1.2.tar.gz:

Publisher: publish-pypi.yml on citedy/citedy-reddit-writer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file citedy_reddit_writer-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for citedy_reddit_writer-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 404bea218ada94a3d36eed0b2b83d8018abf8f8c886896d4d8b82d035179a0b8
MD5 4734827a418b16c4329446a5c34861d5
BLAKE2b-256 e720fb743b41ceac2c03c4cd3765455ce6b02ae710d6718f769470c82b4b27a2

See more details on using hashes here.

Provenance

The following attestation bundles were made for citedy_reddit_writer-0.1.2-py3-none-any.whl:

Publisher: publish-pypi.yml on citedy/citedy-reddit-writer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page