Finds open-source issues that are actually worth your time.
Searching GitHub for label:"good first issue" gives you thousands of results and no way to tell them
apart. Most are traps. The project has been abandoned. The maintainers never reply to outsiders.
Getting it running locally takes a weekend. Someone else is already working on it without saying so.
Compass measures those things ahead of time and ranks issues by whether they are worth five hours of your evening. Then it shows you exactly why it ranked each one that way, so you can disagree with it.
Here is one row of the output:
01. [104] acme/widgets#11 Fix off-by-one in the pagination helper
the project +82 this issue +22
+16 invited (labelled "good first issue") +6 uncontested (1 comment)
responsive · median reply 6h · light setup · TypeScript · 4,200 stars
That says: the maintainers reply to outside pull requests within about six hours, the project is quick
to set up, the issue invites contributors, and nobody else is arguing about it. It also says 82 of
the 104 points came from the project, not the issue — so this is really a recommendation of
acme/widgets, and any of its issues would do.
There is a web interface for all of this, and a command line if you prefer.
- What it actually measures
- What you need first
- Setup, step by step
- Your first run
- Using it
- Reading the output
- Common problems
- Full documentation
Four things, all from public GitHub data. No AI, no language model, no guessing.
| Question | How | |
|---|---|---|
| Maintainer attention | Do they review pull requests from strangers, how fast, and do they merge them? | Reads the last 180 days of external pull requests |
| Setup cost | How much work before you can run the tests, and is there paperwork? | Reads compose files, env templates, task runners, CI config, and any CLA or DCO requirement |
| Issue signals | Is this issue inviting, specified, and unclaimed? | Labels, body length, comment count, age, who filed it |
| Your preferences | Languages and subjects you want, and things to avoid | You set these in the app |
Two of those are measurements. Two are opinions. The tool is careful about which is which, and so should you be — see How ranking works.
A fifth thing is shown but never scored: what your own journal already says about a project. Four rejections in one repository for "needs design discussion first" is that repository telling you something, and it appears beside the row — as a report of what you did, not as a prediction. Nothing has validated it as predictive, so it stays out of the arithmetic.
Every discovery tool ranks open source by stars or by growth. That ranking is close to useless for a contributor, and the reason is not subtle: a project that went from nothing to 119,000 stars in nine months has thousands of drive-by pull requests, one or two maintainers, and no capacity to review yours.
npm run compass -- orgs --momentum risingCompass measures growth from its own star history — dated, yours, and covering repositories no index lists — and then crosses it with whether anyone actually merges outside work:
| Growth surging | Growth normal | |
|---|---|---|
| Maintainers reading outside PRs | rising — the best place to be early |
steady |
| They are not | hype — avoid |
cooling / steady |
hype is never reached from growth alone. "This project is popular" is not a criticism, so the verdict also
requires a measured capacity concern: dormant or slow replies, a hundred or more open pull requests, or a
merge rate at or below 40% over at least ten decided ones.
The combination is the point. Velocity finds what is hot; the responsiveness engine is the only thing that
says whether hot is contributable. In testing, a repository came out hype while its replies read
responsive — because it had 214 open pull requests and the oldest had waited 840 days.
A dash means unmeasured, never "not growing". Velocity needs two star samples a week or more apart, so a freshly discovered repository has none.
The largest remaining way to waste an evening is not picking a bad issue. It is picking one somebody else is already doing.
npm run compass -- claims acme/widgets#412 CONTESTED — several people have asked and nobody was assigned
This is the pattern that wastes evenings: a queue of volunteers and no assignment. Unless you
want to race, spend the time elsewhere.
checked just now
read all 41 comment(s)
7 person(s) asked:
ada 3 days ago — asked to take it
"Can I work on this?"
A good first issue with 23 comments is usually twenty people asking "can I work on this?" and one
person three days in without an assignment. GitHub's assignee field is empty in every one of those
cases, so a label-based list — including this tool's own shortlist until now — calls the whole pile free
work.
One request, only for the issue you actually open, and the answer is cached so shortlist --exclude-claimed can act on it afterwards. A verdict is true as of the moment it was made and is
never shown without its age: free from three weeks ago is nearly worthless. An issue nobody has checked
reads as unknown, never as free.
The question actually asked first is not "which issue" but "which organisations are worth my time?" — and someone wanting to contribute to a growing, well-regarded project usually does not know which organisations exist.
npm run compass -- orgs --gsoc 2026Organisation Maintainers reply? Merge rate Setup Open GSoC
─────────────────────────────────────────────────────────────────────────────────────────────────────────
hog responsive · 9h 86% of 14 1 light 6 2026
acme slow 1/2 · 34h 76% of 37 1 light 1 mod 5 2026
CLA in 1 of 2 repos — resolve before writing code
cern-hsf not in corpus — — 0 2026
Every aggregator lists issues carrying a label, and the official GSoC page gives a description and some technology tags. None of them measures whether maintainers merge work from outsiders. That is what the three middle columns are, and it is the only thing that answers "will anyone read my pull request".
Nothing in that table is a score. The ordering is an ordinal cascade — verdict, merge rate, available
work — so any position can be explained by pointing at a column. Merge rate always carries its
denominator, because 100% of 2 and 76% of 37 are not the same claim. Setup is a distribution rather
than an average, because those are ordinals. Then shortlist --org hog to drill in.
Three things. If you already have them, skip to Setup.
Compass runs TypeScript directly, which needs a recent Node.
Check what you have:
node --versionIf that prints v22.18.0 or higher you are fine. If it prints something lower, or
command not found, install it:
- macOS —
brew install node - Windows — download the LTS installer from nodejs.org
- Ubuntu / Debian —
sudo apt install nodejs npm; if that gives you an older version, use NodeSource - Any system — nvm is the least painful way to manage versions:
nvm install 22 && nvm use 22
This is the database where Compass keeps everything it has learned. Tested on Postgres 16.
psql --versionIf it is missing:
- macOS —
brew install postgresql@16 && brew services start postgresql@16 - Windows — the installer from postgresql.org
- Ubuntu / Debian —
sudo apt install postgresql && sudo systemctl start postgresql - Docker, if you would rather not install it —
docker run -d --name compass-db -e POSTGRES_PASSWORD=compass -p 5432:5432 postgres:16
Compass reads public GitHub data. Without a token you get 60 requests an hour, which is not enough; with one you get 5,000.
Only needed for fetching data. Reading a database you already have needs no token at all.
To create one:
- Go to https://github.com/settings/personal-access-tokens/new
- Give it a name like
compass - Under Repository access, choose Public repositories (read-only)
- Leave every other permission alone
- Click Generate token and copy it — you cannot see it again
Do not grant write, workflow, or organisation permissions. Compass only ever reads public data. A token that can write to your repositories is a token that can damage them if it leaks.
git clone https://github.com/Ashutosh-code-arch/compass.git
cd compass
npm install # the backend and CLI
npm run web:install # the web interfacecreatedb compassIf createdb is not found, or you are using Docker, do it through psql instead:
psql -U postgres -c "CREATE DATABASE compass;"cp .env.example .envOpen .env in any text editor. You need to set two lines:
DATABASE_URL=postgres://localhost:5432/compass
GITHUB_TOKEN=github_pat_paste_yours_hereDATABASE_URL depends on how you installed Postgres:
| How you installed it | Use this |
|---|---|
| Homebrew on macOS | postgres://localhost:5432/compass |
| Ubuntu / Debian default | postgres://postgres@localhost:5432/compass |
| Docker, from the command above | postgres://postgres:compass@localhost:5432/compass |
| With a password | postgres://user:password@localhost:5432/compass |
.envis already in.gitignore. Never commit it.
npm run migrateYou should see:
applied 001_init.sql
applied 002_maintainer_metrics.sql
...
applied 008_stacks_and_full_tree.sql
Run it again and it will say Up to date (13 migration(s) applied). — it is safe to run any number of
times.
npm startThis builds the web interface and starts the server. When it is ready:
Compass listening on http://127.0.0.1:8787
the app is at http://127.0.0.1:8787/
Open http://127.0.0.1:8787 in your browser.
The shortlist will be empty, and that is correct. You have a database but no data in it yet.
Compass needs to build up a picture of some projects before it can rank anything. Do this from the The corpus tab in the app, or from the command line — they do exactly the same work.
The four steps must run in this order, because each one needs the previous one.
npm run compass -- seedRuns a set of searches to discover repositories worth looking at. Takes a couple of minutes and adds roughly a thousand projects.
npm run compass -- sync issues --limit 100The --limit 100 does the first hundred projects only. Start small — this is the slowest step, and
you want to see it working before committing an hour to it. Drop the limit once you trust it.
npm run compass -- sync metrics --limit 100This is the step that makes Compass worth using. It reads the last 180 days of pull requests from outside contributors and works out whether anyone reviews them, how quickly, and how often they get merged.
npm run compass -- sync setup --limit 100Reads each project's compose files, env templates, task runner and CI config to judge how much work it is to get running.
npm run compass -- add django/djangoThis fetches the project, pulls its issues, measures its maintainers and reads its setup cost — one command, ready to rank. Useful when you have a specific project in mind rather than wanting to browse. A project added this way is never paused by pruning.
Reload the app, or:
npm run compass -- shortlistIf nothing appears, run npm run compass -- shortlist --min-score 0 to see everything including the
weak candidates. An empty list at the default threshold usually means metrics have not been collected
yet.
A note on timing. Fetching 1,000 projects fully takes a while and spends most of an hourly GitHub allowance. Compass stops itself before exhausting your quota and picks up where it left off next time, so it is safe to run repeatedly. The
--limitflag is your friend while you are getting a feel for it.
Four tabs:
| Tab | What it is for |
|---|---|
| Shortlist | The ranked issues. Filter on the left, click any row for its full score breakdown. |
| What you decided | Every issue you judged, and how your time estimates compared to reality. |
| What you want | Your languages, subjects, things to avoid, and a star range. Changing these re-ranks everything. |
| The corpus | What data you have, buttons to fetch more, a field to add a project by name, and a banner saying which scan to run next. |
- Open the Shortlist
- Click a row and read the breakdown — decide whether you believe it
- Open the issue on GitHub if it looks good
- Click Record a decision, choose
started, and put in how many hours you think it will take - When you finish, record
merged(orabandoned, or whatever happened) with how long it actually took
Step 5 is the one people skip, and it is the one that matters. After three of those pairs, the What you decided tab starts telling you how far off your estimates run. After about fifteen, the scoring weights stop being guesses.
Everything the app does, plus some reports the app does not have yet:
npm run compass -- add django/django
npm run compass -- shortlist --stack react
npm run compass -- shortlist --language Python --max-setup light
npm run compass -- why owner/name#123
npm run compass -- decide owner/name#123 started --hours 4
npm run compass -- decide owner/name#123 merged --actual-hours 9
npm run compass -- journal
npm run compass -- statusFull list: npm run compass -- --help, or the CLI reference.
The score has no units and predicts nothing. It only puts candidates in order. A 104 is not "twice as good" as a 52, and it does not mean 104 of anything.
What to actually read:
The provenance bar — the project +82 this issue +22. If nearly all the points came from the
project, the tool is recommending the repository, and any of its issues would serve. If a decent
share came from the issue, this particular issue stood out.
The evidence lines — +16 invited (labelled "good first issue"). Every line carries the raw fact
behind it. This is the part to trust; the total is just a sort key.
The stepped meters — responsive, light setup. These are buckets, not percentages, which is why
they are drawn as discrete cells rather than bars. More lit cells means more of the thing; the colour
says whether more is good (attention) or costly (setup).
"Built with" is not a name match. Filtering by react reads declared dependencies and GitHub
topics, so a project called awesome-react-tips will not match and one that quietly depends on React
will. js covers JavaScript and TypeScript; --language JavaScript is the strict form.
A dash means not measured. median reply — means Compass has no data, not that the reply time
is zero. Unmeasured is never treated as bad.
Click Show the full breakdown for every line, split into "the project" and "this issue", with a list of what could not be measured.
Missing DATABASE_URL
Your .env is missing or in the wrong place. It belongs in the repository root, next to
package.json.
ECONNREFUSED when running anything
Postgres is not running. brew services start postgresql@16, or sudo systemctl start postgresql,
or docker start compass-db.
database "compass" does not exist
You skipped Step 2. Run createdb compass.
The shortlist is empty
Try --min-score 0. If that is also empty you have no issues yet — run the four steps in
Your first run. npm run compass -- status shows what data you have.
Everything scores low, or responsiveness not measured everywhere
You have not run sync metrics yet. That is the step that makes the ranking meaningful.
Missing GITHUB_TOKEN when syncing
Add it to .env and restart. Reading existing data does not need a token; fetching new data does.
GitHub 401: Bad credentials
The token is wrong, expired, or has a stray space in it. Generate a fresh one.
A sync stopped early saying the budget is low Working as intended. You are near your hourly GitHub limit. It resumes from where it stopped — wait an hour and run it again.
The web interface says it cannot reach the API
The server is not running. npm start.
More detail: Troubleshooting.
| Document | What is in it |
|---|---|
| Getting started | A longer walkthrough with a complete worked example |
| How ranking works | Every signal, every weight, and which are measured versus assumed |
| CLI reference | Every command and flag, with examples |
| API reference | Every endpoint, with request and response examples |
| Configuration | Every environment variable |
| Database | Tables, columns, and migrations |
| Architecture | Module layout and the rules that keep it testable |
| Development | Tests, conventions, and how to add a signal or a migration |
| Troubleshooting | Errors and what they mean |
| Roadmap | What is built, what is not, and what to do next |
| Design notes | The reasoning, and the corrections real data forced |
Worth knowing before you rely on it:
- The scoring weights have never been validated against an outcome. They are a considered starting position, not a model fitted to anything. Recording your decisions is what fixes that.
- Framework detection has a fixed vocabulary of 34 common frameworks and libraries. A project built on something outside that list shows no "built with" tag — absent, not absent-of-tech.
- Single user. No accounts, no authentication, bound to localhost. Do not put it on a network.
- Everything is a snapshot. Maintainer behaviour changes; a metric from a month ago may be stale.
Re-run
sync metricsoccasionally.
No licence file is included — add one before publishing. If you want others to use and modify this, MIT is the usual choice; choosealicense.com walks through the options.