Skip to content

feat(tcfeed): read GitHub search as well as the subreddit - #114

Merged
ralyodio merged 2 commits into
masterfrom
worktree-tcfeed-github-search
Aug 13, 2026
Merged

feat(tcfeed): read GitHub search as well as the subreddit#114
ralyodio merged 2 commits into
masterfrom
worktree-tcfeed-github-search

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Adds the API behind search?q=stars:1000&type=repositories&s=updated&o=desc as a second source, merged with the reddit posts and deduplicated.

tcfeed: 44 to consider — 40 from r/coolgithubprojects, 4 from search (stars:1000)

Deduplicated because a repository trending on reddit is exactly the kind that also turns up in a search sorted by recent activity, and cloning it twice in one run is the one thing worth avoiding here.

stars:1000 means exactly a thousand

Not a thousand or more. That reads like a typo and is not one — it is the query in the URL, and it is a narrow, oddly effective band: popular enough that somebody is watching, small enough that nobody has audited it yet. stars:>=1000 returns a different and far larger set, so the distinction is documented rather than silently "corrected".

Variable Default
TCFEED_GH_QUERY stars:1000 any GitHub search qualifier
TCFEED_GH 25 how many come back; 0 turns the source off

Asked through gh so it uses the token already on the machine. The HTML page is rate-limited hard for anyone not signed in, and parsing it would be a scraper of a page that changes shape without warning.

Either source may now fail on its own

This is the part that matters more than the new source. Reddit refuses this address often enough that making it fatal meant a run produced nothing on an afternoon when the search was answering perfectly. Now whichever source came back is scanned, a source that failed says why rather than looking empty, and only losing every source that was asked is an error.

Archived and forked repositories are dropped at the search rather than left for metadata() to reject one HTTP call later, because the search already knows.

Verified

tsc --strict clean, and all three paths exercised against the live APIs with TCFEED_MAX=0 so nothing was cloned:

Case Result
both sources up 44 to consider — 40 from r/coolgithubprojects, 4 from search (5 requested, 1 dropped as archived)
reddit dead, search up reddit: could not read r/… (HTTP 404) then 4 to consider — 0 from …, 4 from search — run continues
both dead/off no source answered, exit 1

🤖 Generated with Claude Code

Adds the API behind
https://github.com/search?q=stars:1000&type=repositories&s=updated&o=desc
as a second source, merged with the reddit posts and deduplicated - a
repository trending on reddit is exactly the kind that also turns up in
a search sorted by recent activity, and cloning it twice in one run is
the one thing worth avoiding.

Asked through gh so it uses the token already on the machine. The HTML
page is rate-limited hard for anyone not signed in, and parsing it
would be a scraper of a page that changes shape without warning.

The default query is `stars:1000` exactly as that URL has it, and it
means *exactly* a thousand stars rather than a thousand or more. That
reads like a typo and is not one: it is a narrow, oddly effective band
- popular enough that somebody is watching, small enough that nobody
has audited it yet - and `stars:>=1000` would return a different and
far larger set. TCFEED_GH_QUERY overrides it, TCFEED_GH caps how many
come back, and TCFEED_GH=0 turns the source off.

Either source may now fail on its own. Reddit refuses this address
often enough that making it fatal meant a run produced nothing on an
afternoon when the search was answering perfectly; now whichever source
came back is scanned, a source that failed says why rather than looking
empty, and only losing every source that was asked is an error.

Archived and forked repositories are dropped at the search rather than
left for metadata() to reject one HTTP call later, because the search
already knows.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

67 finding(s)

HIGH/CRITICAL: 11 | MEDIUM: 55 | LOW: 1

Severity Rule Location
HIGH secret-aws-access-key prd/0003-detect-hardcoded-secrets-before-they-are-committed-or-served.md:126
HIGH sh-eval-expansion .githooks/pre-commit:26
HIGH sh-remote-script-execution apps/web/public/install.sh:272
HIGH sh-remote-script-execution apps/web/public/install.sh:320
HIGH secret-generic-credential modules/spend-guard/config/example.conf.toml:13
HIGH secret-generic-credential modules/spend-guard/README.md:84
HIGH secret-generic-credential PRD.md:268
HIGH tls-verification-disabled prd/0004-find-dangerous-code-patterns-without-pretending-to-be-a-compiler.md:121
HIGH tls-verification-disabled prd/0004-find-dangerous-code-patterns-without-pretending-to-be-a-compiler.md:122
HIGH sh-remote-script-execution scripts/smoke-test.sh:46
HIGH sh-remote-script-execution scripts/smoke-test.sh:47
MEDIUM insecure-temp-file .githooks/commit-msg:16
MEDIUM insecure-temp-file .githooks/post-commit:20
MEDIUM js-shell-exec-interpolation apps/cli/src/commands/init.ts:70
MEDIUM js-shell-exec-interpolation apps/cli/src/commands/init.ts:79
MEDIUM js-shell-exec-interpolation apps/cli/src/commands/service.ts:88
MEDIUM js-shell-exec-interpolation apps/cli/src/commands/service.ts:111
MEDIUM sql-template-interpolation apps/cli/src/core/state.ts:121
MEDIUM sql-template-interpolation apps/cli/src/core/state.ts:125
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:31
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:33
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:34
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:35
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:36
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:43
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:49
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:56
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:63
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:82
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:84
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:85
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:93
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:98
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:105
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:112
MEDIUM js-shell-exec-interpolation apps/cli/src/index.ts:419
MEDIUM js-unescaped-html-sink apps/web/src/app/about/page.tsx:180
MEDIUM js-unescaped-html-sink apps/web/src/app/about/page.tsx:184
MEDIUM js-open-redirect apps/web/src/app/auth/login/page.tsx:50
MEDIUM js-unescaped-html-sink apps/web/src/app/blog/[slug]/page.tsx:125
MEDIUM js-unescaped-html-sink apps/web/src/app/blog/[slug]/page.tsx:153
MEDIUM js-unescaped-html-sink apps/web/src/app/blog/[slug]/page.tsx:157
MEDIUM js-unescaped-html-sink apps/web/src/app/get-whitepaper/page.tsx:346
MEDIUM js-unescaped-html-sink apps/web/src/app/layout.tsx:211
MEDIUM js-unescaped-html-sink apps/web/src/app/layout.tsx:215
MEDIUM js-unescaped-html-sink apps/web/src/app/layout.tsx:219
MEDIUM js-unescaped-html-sink apps/web/src/app/page.tsx:120
MEDIUM js-unescaped-html-sink apps/web/src/app/store/[slug]/page.tsx:107
MEDIUM js-open-redirect apps/web/src/components/funding/FundingClient.tsx:97
MEDIUM manifest-install-lifecycle-script package.json:24

…and 17 more. Full results in the Security tab.

Snippets are redacted; ThreatCrush never prints matched credential material.

More than a thousand stars, sorted by most recently pushed, which is
the band actually wanted: exactly-1000 was a sliver of a few hundred
repositories that emptied out as they gained a star.

The qualifier is `stars`, and it is worth being careful about.
`starts:>1000` is not an error - it is a free-text search for the word,
and it returns repositories with no stars at all, which is a query that
looks like it worked. Noted in the header and beside the default.

Practical consequence, measured over the first 20 results: 8 exceed the
300MB TOO_BIG_KB cap and are skipped (supabase 2371MB, openclaw 2458MB,
metabase 2122MB), leaving 12 scannable. The size check downstream does
considerably more work with this query than the feed ever gave it,
because a repository with this many stars is often a monorepo. The cap
is left where it is: an afternoon spent cloning a gigabyte is the thing
it exists to prevent.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ralyodio

Copy link
Copy Markdown
Contributor Author

Default query changed to stars:>1000 in 10be5e6 — more than a thousand, not exactly a thousand. Matches the corrected URL.

tcfeed: 50 to consider — 40 from r/coolgithubprojects, 10 from search (stars:>1000)

starts: is a trap worth naming

The qualifier is stars. starts:>1000 is not an error — GitHub treats it as a free-text search for the word, and it happily returns repositories with no stars at all:

$ gh search repos "starts:>1000" --sort updated --limit 3
maisymylod/apex-portfolio        0 stars
kyawlay998078-stack/my-website-  1 star
markgillogly2-blip/index.html    0 stars

A query that is wrong in that direction looks like it worked, so it is called out in the header and beside the default.

Measured consequence: 40% are too big to scan

stars:>1000 returns much larger repositories than the feed ever did. Over the first 20 results, 8 exceed the 300MB TOO_BIG_KB cap:

Repo Size
openclaw/openclaw 2458 MB
supabase/supabase 2371 MB
metabase/metabase 2122 MB
twentyhq/twenty 1559 MB
frappe/frappe 793 MB
openclaw/Peekaboo 632 MB
lightdash/lightdash 486 MB
polarsource/polar 461 MB

12 scannable, 8 skipped. The cap is deliberately left where it is — an afternoon spent cloning a gigabyte is exactly what it exists to prevent — but it means the effective yield of this source is roughly 60% of TCFEED_GH, so set that number with the discard in mind.

@ralyodio
ralyodio merged commit 15b60ca into master Aug 13, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant