Loading...
E.G.

Auditing an Open-Source Ecosystem: 1,434 Repos

August 20, 2026
Table of Contents

Last month I built a curated list of free and open-source tooling for Generative Engine Optimization. One rule decided every entry: the project has to be runnable by you, and published under an OSI-approved licence. Everything else followed from that.

I did not want to pick from memory, so I wrote the selection down as a procedure and ran it. This is that procedure, with the numbers from a fresh run on 14 August 2026. It is not specific to GEO — the same four steps work on any ecosystem where you need to know what you are allowed to depend on.

Step 1: sweep, don't browse

Browsing GitHub gives you what is popular with people who write about GitHub. A search sweep gives you the tail as well. I used fifteen queries — eight topic queries and seven keyword queries — and paged two deep on each.

for q in \
  "topic:generative-engine-optimization" "topic:answer-engine-optimization" \
  "topic:llms-txt" "topic:ai-visibility" "topic:ai-seo" "topic:llm-seo" \
  "topic:ai-search" "topic:aeo" \
  "llms.txt generator in:name,description,readme" \
  "generative engine optimization in:name,description" \
  "answer engine optimization in:name,description" \
  "AI visibility tracking in:name,description" \
  "ai crawler robots.txt in:name,description" \
  "schema.org json-ld generator in:name,description" \
  "brand mentions LLM in:name,description"
do
  for page in 1 2; do
    curl -s -H "Accept: application/vnd.github+json" \
      --get --data-urlencode "q=$q" --data "per_page=100&page=$page" \
      https://api.github.com/search/repositories \
    | jq -r '.items[] | [.full_name, .stargazers_count, .archived,
                         .pushed_at, (.license.spdx_id // "none")] | @tsv'
    sleep 7
  done
done | sort -u > repos.tsv

The seven-second sleep is the unauthenticated search rate limit, which is ten requests per minute. With a token it is thirty and you can drop it to two. Fifteen queries came back with 1,434 unique repositories.

Most of them are noise. The keyword queries in particular pull in user-agent parsers, Telegram bots, and at one point a C# cheat sheet that mentions llms.txt once. That is the point of sweeping wide — you filter afterwards, and you can see what you filtered.

Step 2: the filter matrix

Four fields, all of which the search API already returns, so this costs no extra requests. Drop anything archived, because an archived repo is a dead dependency. Drop anything not pushed to in twelve months, which is not a quality signal on its own but does separate maintained from abandoned. Drop anything under 30 stars, which I will come back to. Keep the SPDX licence id for step 3, because that is the field doing the real work.

unique hits                     1434
not archived                    1425
pushed within 12 months         1353
at least 30 stars                133
OSI-approved SPDX id              94

The star floor is the crude one. It removes 1,220 repositories in a single step, and some of them are good — a new tool by someone who has not marketed it yet looks identical to an abandoned experiment. I kept it because I could not review 1,353 READMEs, and I would rather state the arbitrary cut than pretend the list is exhaustive. If you rerun this with a floor of 10, expect roughly three times the reading.

Step 3: the licence check, which is not a formality

Of the 133 repositories that survived, 94 carry an OSI-approved licence. The other 39 split into two groups that deserve to be described separately, because conflating them would be unfair to both.

23 have no licence file at all. Under default copyright law that means all rights reserved. You have no granted right to use, modify or redistribute the code, regardless of how public the repository is or how obviously the author intended you to use it. The largest of these has 3,534 stars. Several belong to a commercial scraping vendor publishing sample code, where the omission is probably deliberate. Others are clearly an oversight by someone who added a README and moved on.

16 have a licence file that GitHub cannot map to an SPDX identifier. GitHub reports these as NOASSERTION, which is not the same finding at all. It usually means a custom text, a Creative Commons variant, or a dual-licence note. Those need reading, not excluding. Two of them ended up on my list after I read them.

Then there is the category the SPDX field will not catch: source-available licences that read as open source at a glance. BSL, FSL and SSPL all publish the source and all restrict what you may build with it. The Functional Source License converts to Apache-2.0 after two years, which is a reasonable commercial choice and still not open source today. I cut one 99-star AEO monitoring platform on exactly that basis.

None of this is an accusation. A missing licence file is usually an oversight, and picking a source-available licence is a legitimate business decision. But if a list calls itself open source without checking, the label carries no information, and someone will take a dependency on the basis of it.

The licence distribution among the 94 that passed is narrower than I expected: 62 MIT, 19 Apache-2.0, 6 AGPL-3.0, 3 CC0-1.0, and one each of GPL-3.0, GPL-2.0 and MPL-2.0.

Step 4: read the README of everything you keep

A repository description is marketing copy written by the author. A third-party blog summary is that same copy, paraphrased by someone who also did not run the tool.

The clearest case I hit: one visibility tracker drives the real chat interfaces in a browser rather than calling the model APIs. That is the entire reason it exists — API completions routinely differ from what the chat surface renders to a user — and it is not in the repository description. I would have filed it next to six API-based trackers and been wrong about what it does.

I also sanity-checked the outliers. A brand-new SEO skill repository with 12,000 stars is worth a look at its star-to-fork ratio and its creation date before you vouch for it in public. The last step was mechanical: curl every link for a 200 before publishing. All 64 of them. Two had moved.

What this costs, and what it is worth

The sweep runs in about four minutes. The filtering is a few lines of jq. Reading the READMEs of everything that survives took the better part of a day, and that is where the whole value sits — the automated part only decides what you have to read.

The result is 62 entries. The number I keep coming back to is the other one: 17% of the maintained, non-trivial projects in this space cannot legally be used by anyone. That is not a GEO problem. Run the same four steps on the ecosystem you depend on and see what comes back.

Contacting the maintainers

I sent a handful of mails after publishing, and the framing mattered more than the content. The two cold requests I sent in July went unanswered, which was the correct outcome for a message with nothing in it for the recipient. Telling someone they were included, and asking whether I described their project correctly, is a different message. It is useful to receive, and a correction is a real thing to reply with.

I picked ten of the 58 listed maintainers on the likelihood of a reply rather than on prominence: an individual owner rather than an organisation, because one person decides and answers; between 30 and 800 stars, because visibility still matters at that size; a recent push, because an active maintainer reads their mail; a public contact address or a real blog; and thematic adjacency, so a reply can turn into a conversation.

Three mails went out. None have been answered so far, which I am reporting because the alternative would be to only publish the outreach numbers that flatter the method.

Does a missing licence file mean the code is public domain?

No. It means the opposite. Without an explicit licence the default is all rights reserved, so a public repository with no LICENSE file grants you no rights at all, however freely it was published.

Is source-available the same as open source?

No. BSL, FSL and SSPL publish the source but restrict what you may build with it, which fails the OSI definition. FSL converts to Apache-2.0 after two years, so a given release becomes open source eventually while the current one is not.

What does NOASSERTION mean on GitHub?

That GitHub found a licence file but could not match it to a known SPDX identifier, usually because it is a custom text or a variant. It is a prompt to read the file, not evidence that the project is unlicensed.

Related articles