superx-cli 0.6.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.1 (2026-09-18)
4
+
5
+ - New skill Worth a Reply (worth-a-reply): `posts:triage` reads a topic, then the skill hands back the posts worth replying to, ordered by how much room there is to add something in a reply, each with its link, one line on why and the angle a reply could take. Skim posts come back as one-liners and the Pass pile stays out unless the person asks. It drafts nothing until they pick a post. Skills are now 32.
6
+
7
+ ## 0.7.0 (2026-09-18)
8
+
9
+ - `posts:triage "<query>"` searches recent public posts on a topic and sorts them into Read, Pass or Not sure, up to 40 posts a run. Every post comes back with its lane, a `pct`, a kind (insight, story, data, progress, news, question, intro, launch, joke or opinion) and the yes/no answers behind the call: specific and informative, says something new, engagement bait, a plug, a platitude, and room to add something in a reply. `pct` is how CLEAR the call was and not how good the post is: on `read` and `pass` it runs 50 to 99, so a `pass` at 99 is confidently not worth reading, and only on `unsure` is it the raw worth-reading score. Read it with the lane, never alone. `--days 1-7` sets how far back to look (default 3), `--account` attributes the run. What is judged is the TEXT of a post and never who wrote it, so it is a call on the writing, not a rating of a person. The search asks for original posts, English only, with a floor of 30 likes, and never returns replies or reposts. 2 credits a run, a daily cap per plan, and 1 live lookup for a single-word query or 2 for a multi-word one. Nothing is posted, saved or sent
10
+ - MCP `triage_posts` does the same thing with the same fields. Reconnect the server to pick it up
11
+
3
12
  ## 0.6.0 (2026-09-18)
4
13
 
5
14
  - Skills layout: the skill now lives at `skills/superx/`, one folder per SuperX skill under `skills/superx/references/skills/<id>/` (`recipe.md` for the agent, `card.json` for the app). `SKILL.md` is route-first and under 500 lines: the command list moved verbatim to `references/commands.md`, the growth strategy guide to `references/growth-strategy.md`, and the skills index is generated. The root `SKILL.md`, `PLAYBOOK.md` and `PLAYBOOKS.md` are gone, and "playbook" is now only the name of the SuperX blog freebie
package/dist/index.js CHANGED
@@ -201,6 +201,10 @@ var SuperXAPI = class {
201
201
  async viralScore(body) {
202
202
  return (await this.request("/posts/viral-score", { method: "POST", body })).json;
203
203
  }
204
+ /** Sort recent public posts on a topic into Read, Pass or Not sure. */
205
+ async triage(body) {
206
+ return (await this.request("/posts/triage", { method: "POST", body })).json;
207
+ }
204
208
  /** Draft ONE reply to a post. Text only: a person posts it. */
205
209
  async draftReply(body) {
206
210
  return (await this.request("/engage/reply-draft", { method: "POST", body })).json;
@@ -811,6 +815,23 @@ async function postsViralScore(argv) {
811
815
  const api = new SuperXAPI(getConfig());
812
816
  printJson(await api.viralScore(body));
813
817
  }
818
+ async function postsTriage(argv) {
819
+ if (!argv.query || !argv.query.trim()) {
820
+ note('Provide a query: superx posts:triage "coding agents".');
821
+ process.exit(1);
822
+ }
823
+ if (argv.days !== void 0) {
824
+ if (!Number.isInteger(argv.days) || argv.days < 1 || argv.days > 7) {
825
+ note("--days must be a whole number of days between 1 and 7.");
826
+ process.exit(1);
827
+ }
828
+ }
829
+ const body = { query: argv.query };
830
+ if (argv.days !== void 0) body.max_age_days = argv.days;
831
+ if (argv.account) body.account_id = argv.account;
832
+ const api = new SuperXAPI(getConfig());
833
+ printJson(await api.triage(body));
834
+ }
814
835
 
815
836
  // src/commands/tools.ts
816
837
  async function toolsInlineEdit(argv) {
@@ -2728,6 +2749,19 @@ var advancedSettingsOptions = (y) => y.option("auto-retweet", {
2728
2749
  "The score compares this draft with the account's OWN recent posts. It is not a reach prediction and it knows nothing about follower count. Rewrite and score again until the score stops rising, and read any warnings as a stop sign: asking for replies or sending readers off the platform can never raise it."
2729
2750
  ),
2730
2751
  run(postsViralScore)
2752
+ ).command(
2753
+ "posts:triage <query>",
2754
+ "Sort recent public posts on a topic into Read, Pass or Not sure (costs AI credits)",
2755
+ (y) => accountOption(y).positional("query", {
2756
+ describe: "Topic, phrase or search expression (2-80 characters)",
2757
+ type: "string"
2758
+ }).option("days", {
2759
+ describe: "How far back to search, 1 to 7 days (default 3)",
2760
+ type: "number"
2761
+ }).example('$0 posts:triage "coding agents"', "What is worth reading on a topic today").example('$0 posts:triage "indie SaaS" --days 7', "The past week instead of the past three days").epilogue(
2762
+ "Judges the TEXT of each post and never sees who wrote it, so read the result as a call on the writing rather than a rating of a person. Up to 40 posts a run, 2 credits, and each plan has a daily cap. Nothing is posted, saved or sent."
2763
+ ),
2764
+ run(postsTriage)
2731
2765
  ).command(
2732
2766
  "replies:list",
2733
2767
  "List replies the account has sent (newest first)",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superx-cli",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "description": "SuperX CLI - command line interface to the SuperX API for Twitter/X growth: read posts and analytics, find engaged contacts, and schedule posts and threads",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -189,6 +189,7 @@ scoping are in [references/skills/README.md](./references/skills/README.md).
189
189
 
190
190
  ### Replies & Engagement
191
191
  - **Reply Sprint**: The replies your posts got, each with a ready-to-send draft. -> references/skills/reply-sprint/recipe.md
192
+ - **Worth a Reply**: Let Jev read your niche and hand you the posts worth replying to today. -> references/skills/worth-a-reply/recipe.md
192
193
  - **Reply to Any Post**: Paste any post, get the context and a strong reply. -> references/skills/reply-to-any-post/recipe.md
193
194
  - **My Replies Report**: Which of your replies actually earn attention. -> references/skills/my-replies-report/recipe.md
194
195
  - **Who Is This Person?**: A fast read on any public account, plus your history with them. -> references/skills/who-is-this-person/recipe.md
@@ -372,6 +372,10 @@ superx tools:factcheck --text "X has 600M daily active users"
372
372
  # Score a draft against this account's own normal post, then improve it
373
373
  superx posts:viral-score --text "$(cat draft.txt)"
374
374
  superx posts:viral-score --text "$(cat draft-v2.txt)" --image
375
+
376
+ # Sort what people are posting on a topic into Read, Pass or Not sure
377
+ superx posts:triage "coding agents"
378
+ superx posts:triage "indie SaaS" --days 7
375
379
  ```
376
380
 
377
381
  - **Every one of these returns TEXT and posts NOTHING.** `engage:reply-draft` writes a reply for a person to review and post; there is still no reply-sending command anywhere in the CLI. Show the draft, let the user edit it, and never say a reply went out.
@@ -381,7 +385,8 @@ superx posts:viral-score --text "$(cat draft-v2.txt)" --image
381
385
  - `tools:rephrase` presets: improve, grammar, translate, hook, details, clarity, engaging, humorous, positive, creative, sarcastic, inspirational, concise. The style ones write in the user's voice; grammar, translate, clarity, details and concise stay mechanical.
382
386
  - `tools:factcheck` reports `result` (true, false or unknown), a one-sentence `comment` and the `sources` it read. It is a model's reading of a couple of search results, NOT a guarantee: show the sources and never present the verdict as settled.
383
387
  - `posts:viral-score` scores ONE draft from 0 to 100 against the account's OWN recent posts, with `helped` / `hurt` in plain English and an expected multiple per counter (`reposts_and_quotes` and `views` come back `confidence: "low"`, so say so). It is not a reach prediction and it knows nothing about follower count. Rewrite what `hurt` names, score again, and stop when the score stops rising: three or four rounds is the useful range. NEVER chase the score with reply bait - anything in `warnings` (asking for replies, inviting people to connect, a borrowed template, sending readers off the platform) can only push a score DOWN, so a warning means change the post, not work around it. The baseline is the account's originals from the past 90 days, minus the last 3 days whose numbers are still settling; `baseline.kind: "population"` means fewer than 10 of those were usable and the draft was scored against the average training post instead.
384
- - Costs are measured AI credits: typically 1 each, and 2 for a remix or a reply draft. None of them spends a live X request except `engage:reply-draft --post`.
388
+ - `posts:triage "<query>"` is the only one here that reads other people's posts: it searches recent public posts on a topic (`--days` 1-7, default 3) and sorts up to 40 of them into `lane` `read`, `unsure` or `pass`, each with `pct`, a `kind` (insight, story, data, progress, news, question, intro, launch, joke, opinion) and the `answers` behind the call. Quote a post's own answers when you say why it landed where it did, and never invent a reason. **`pct` is how CLEAR the call was, not how good the post is:** on `read` and `pass` it runs 50 to 99, so a `pass` at 99 means confidently NOT worth reading, and only on `unsure` is it the raw worth-reading score. Always say the lane with the number, never rank posts by `pct` across lanes, and never call a 90 a great post without checking the lane first. What is judged is the TEXT of a post and the model never sees who wrote it, so report it as a call on the writing, NOT as a rating of a person or an account. The search asks for original posts, English only, with a floor of 30 likes, and never returns replies or reposts: a small or brand-new topic can come back empty, which is an honest answer rather than a failure. The floor is what the search asks for, not a promise about `counts.likes`, so do not tell the user every post has 30+ likes. `posts_searched` says how many distinct posts the searches found before the 40-post cap. Nothing is posted, saved or sent.
389
+ - Costs are measured AI credits: typically 1 each, 2 for a remix or a reply draft, and a flat 2 for a triage run. None of them spends a live X request except `engage:reply-draft --post` and `posts:triage`, which spends the searches it runs; both also carry a per-plan daily cap.
385
390
 
386
391
  ### Workers (posts written for you on a schedule)
387
392
 
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "Worth a Reply",
3
+ "category": "replies-engagement",
4
+ "order": 15,
5
+ "subtitle": "Let Jev read your niche and hand you the posts worth replying to today.",
6
+ "summary": "Searches recent public posts on a topic and reads every one of them, then sorts them into three lanes: Read, the ones worth your time, Skim, the maybes, and Pass, which stays greyed out and is never listed unless you ask for it. The Read posts come back ordered by how much room there is to add something in a reply, each with its link, one line on why it is worth a reply and an angle you could take. It reads the words of a post and never who wrote it, so it is a call on the writing and not a rating of a person. Nothing is drafted or sent unless you ask.",
7
+ "howToAsk": [
8
+ "What should I reply to in AI agents today?",
9
+ "Find me 5 posts worth replying to about indie SaaS",
10
+ "Anything worth replying to on coding agents this week?"
11
+ ],
12
+ "provide": "a topic, and optionally how many days back (1 to 7).",
13
+ "get": "the posts worth a reply, each with a link, one line on why and an angle, then the Skim list.",
14
+ "chips": [
15
+ "2 credits on the API and CLI",
16
+ "Up to 40 posts",
17
+ "Judges the text, never the author",
18
+ "Nothing is sent"
19
+ ],
20
+ "launchPrompt": "Find me the posts worth replying to on a topic today. Search recent posts on it, sort them into Read, Skim and Pass, and show the Read posts first, ordered by how much room there is to add something in a reply: one post per line with its link, its kind, one line on why it is worth a reply and the angle a reply could take, all taken from that post's own answers and text. Then list Skim as short one-liners. Leave the Pass pile out unless I ask for it, and do not draft any replies until I pick one. Here is the topic: ",
21
+ "sampleKind": "recap"
22
+ }
@@ -0,0 +1,16 @@
1
+ # Worth a Reply
2
+
3
+ Read a topic the person cares about and hand back the posts worth replying to today, each with the angle a reply could take.
4
+
5
+ ```bash
6
+ superx posts:triage "<the topic>" --days 3 # --days 1-7, default 3; one run per topic per day is plenty
7
+ superx engage:reply-draft --post <id> --thoughts "<what the person wants to say>" # only after they pick one
8
+ ```
9
+
10
+ Read `lane`, `pct`, `kind` and `answers` from every post. Present the `read` lane first, ordered by `answers.r_reply_room` (how much room a knowledgeable reader has to add something), and order ONLY inside that lane: one line per post with its `url`, its `kind`, one line on why it is worth a reply built from that post's own answers (`r_specific` says it names something concrete, `r_new` says it is not the usual take, `r_reply_room` says there is something left to add), and one line on the angle a reply could take, drawn from the post's text. Then the `unsure` lane as short one-liners under a Skim heading. Leave the `pass` lane out entirely unless the person asks what was dropped, and then say how many and why in one sentence. Quote a post's own answers rather than inventing a reason, and never claim a post has a given like count from the search floor.
11
+
12
+ `pct` is how CLEAR the call was, not how good the post is: on `read` and `pass` it runs 50 to 99, so a `pass` at 99 means confidently not worth the time, and only on `unsure` is it the raw worth-reading score. Say the lane with the number, never rank posts by `pct` across lanes. What is judged is the TEXT of a post and the model never sees who wrote it, so report it as a call on the writing and never as a rating of a person or an account. The search asks for original posts, English only, with a floor of 30 likes, and returns no replies or reposts, so a small or brand-new topic can come back empty, which is an honest answer rather than a failure.
13
+
14
+ MCP: `triage_posts` -> `draft_reply` only when the person picks a post and says what they want to say
15
+
16
+ Stops at: a reply list, in chat, for the person to pick from. It drafts nothing until they choose a post, and nothing is ever sent. A run costs a flat 2 credits and spends 1 live X lookup for a single-word topic or 2 for a multi-word one, out of the account's daily allowance.