Check what watched contacts are posting on X, surface engagement opportunities. Reads Profiles/Contacts.md for handles.
Monitor X/Twitter activity from contacts in the network. Surface posts worth engaging with, batch reply decisions via AskUserQuestion.
Read Profiles/Contacts.md. Extract X/Twitter handles from ALL sections:
For each handle, also check the Filter column. If a filter string exists, that handle requires keyword-filtered search (see Step 2).
Build a handle list. Skip contacts with no X handle. Report how many handles found.
If no handles found, say so and stop.
Before searching contacts, check whether this skill already ran earlier today:
xurl search "from:[your-handle]" -n 20
Look at the reply timestamps. If there's a cluster of replies today (indicating an earlier watch-contacts session or manual engagement), use the as the floor timestamp. Only surface tweets posted AFTER this floor.
If the floor is very recent (< 2 hours ago), warn: "Ran recently — there may be few new posts." and proceed anyway.
For each handle, search for the 3 most recent tweets:
# Standard (no filter):
xurl search "from:{handle}" -n 10
# Filtered (high-volume posters — use separate queries, not OR):
xurl search "from:{handle} claude" -n 10
xurl search "from:{handle} openclaw" -n 10
xurl search "from:{handle} agent" -n 10
# Deduplicate by tweet ID across filter queries.
Filter syntax note: The X search API does not scope OR to the from: clause. from:X foo OR bar returns (from:X foo) OR (bar globally). For filtered handles, run one search per keyword and deduplicate results by tweet ID.
From each handle's results, keep only the 3 most recent tweets.
Floor timestamp cutoff: Discard any tweet older than the floor timestamp from Step 1.5. If a handle has no tweets after the floor, skip it entirely.
Run searches in parallel where possible.
From all remaining tweets (max 3 per handle, last 24h only), identify posts worth engaging with. Prioritize:
Skip: retweets without commentary, promotional/spam, posts with 0 relevance to [Your Name]'s work, short replies to other people with no standalone value.
Present results in batches of up to 4 using AskUserQuestion (tool limit: 4 questions max). Each batch contains up to 4 questions, one question per post. Each question is a single yes/no decision for one reply.
Question format:
@handle | https://x.com/handle/status/tweet_id | Xh ago | N replies | N likes | N imp
"[full tweet text, truncated at ~200 chars if needed]"
Draft: [reply text]
Post this reply?
@handle (max 12 chars — truncate handle if needed)[{"label": "Post it", "description": "Reply from @[your-handle]"}, {"label": "Skip", "description": "Don't reply to this one"}]Context fields: Calculate hours since posted from created_at. Use reply_count, like_count, impression_count from public_metrics. Build the tweet link from https://x.com/{handle}/status/{tweet_id}.
[Your Name] decides each reply independently:
xurl reply.Also classify each surfaced post internally as one of:
reply nowsave for laterarticle seednot worth touchingOnly present reply now items in the approval batch. Keep the others in the verbal summary.
If more than 4 actionable posts, present multiple batches sequentially (4 questions per batch).
If nothing worth engaging with: "Nothing actionable in the last 24h. [N] contacts checked, [M] posts scanned."
For each "Post it" reply, check reply eligibility first:
xurl "/2/tweets/{tweet_id}?tweet.fields=reply_settings,conversation_id,author_id,created_at,public_metrics"
If reply_settings indicates the post is effectively public or otherwise open to reply, proceed.
Do not assume "not tagged" means blocked.
For each eligible "Post it" reply, attempt to post:
xurl reply [tweet_id] "[reply text]"
If xurl reply fails despite passing the eligibility check, fall back to copying the draft to clipboard and providing the link. One at a time — copy draft, show link, wait for [Your Name] to say "next" before copying the next one.
printf '%s' "draft reply text" | pbcopy
After ALL batches are complete, verify every post that was presented (both approved and skipped). For each original tweet, check whether a reply from @[your-handle] exists:
xurl search "from:[your-handle] to:handle" -n 5
Report results in a summary table:
| Post | Status | Reply |
|---|---|---|
| @handle — [short tweet ref] | Posted by Jules / Posted directly / No reply | [first ~80 chars of reply if found] |
Voice sample capture: For any reply [Your Name] posted directly (i.e., NOT posted by Jules but a reply from @[your-handle] exists on that tweet), read the full reply text and append it as a new sample to Profiles/Voice-Samples-Raw.md. Use this format:
### X Reply — @handle ([date])
[full reply text]
These direct replies are authentic voice samples — [Your Name] wrote them manually, making them high-quality calibration data.
After verification: "Want to add or remove anyone from the watch list? I'll update Profiles/Contacts.md."
[Your Name]'s voice — practitioner, not fan. Specific, not generic. References real experience building with AI agents, Claude Code, or shipping products. Never sycophantic. Short (1-3 sentences max).
Profiles/Contacts.md.@[your-handle] as the authority account. @builtwithjules is for tagged or assistant-perspective replies, not default relationship building.