This file is read by coding agents (Jules, OpenHands, Codex, and others that
honor the AGENTS.md convention) when they work on this repository.
Both Jules and OpenHands are wired up. Issues are routed automatically:
- Issues labeled
jules→ handled by Jules (https://jules.google). - Issues labeled openhands (and a comment starting with @openhands) → handled by OpenHands (https://app.all-hands.dev).
One issue, one agent. A label-exclusivity workflow
(enforce-agent-labels.yml) auto-removes a duplicate agent label if both
end up on the same issue. If you somehow see both jules and openhands on
an issue, do not act on it — the workflow will resolve the conflict
within seconds.
Don't redo work that's already in flight. Before starting, check if
there's an open PR with Closes #<this-issue> or a branch named after
the slug (fix-<slug> or add-<slug>). If so, the other agent or a
human is already on it; stop and post a comment.
As a safety net, dedup-pull-requests.yml auto-closes any new PR that
references the same Closes #N as an older open PR. The lower-numbered
PR wins. If your PR gets auto-closed for this reason and the older one
is broken, the comment will tell you how to take over deliberately.
Always rebase before pushing. Because data/companies.yml is a single
shared file, two concurrent fix-PRs editing different slugs can still
collide on adjacent lines or on README per-category counts. Run
git pull --rebase origin main and resolve any conflict before pushing.
This repository is a curated Awesome list of hiring companies. The
machine-readable source of truth is data/companies.yml; README.md and the
files under docs/categories/ are the human-readable mirror.
- Add a company — usually a name and a careers URL.
- Fix a broken or moved careers URL.
- Correct an ATS slug (Greenhouse, Lever, Ashby, Workday, etc.).
- Remove a dead listing.
Touch all three places together — they must stay consistent:
data/companies.yml— add the entry, alphabetized within its category.README.md— update the per-category company count if you changed totals.docs/categories/<category>.md— add or update the company line.
Every entry needs: name, slug, domain, careers_url, category, ats,
tags, sources. See existing entries for the exact shape, and the
Field format rules below for what each one must look like.
The schema (schemas/company.schema.json) enforces specific patterns.
Common failures from agent-generated PRs come from getting these wrong:
slug— lowercase kebab-case ASCII. Pattern:^[a-z0-9]+(?:-[a-z0-9]+)*$. Derive fromnameby lowercasing and collapsing any non-alphanumeric run into a single-. Examples:OpenAI→openai,Acme Inc.→acme-inc,1Password→1password.domain— lowercase bare domain only. Nohttps://, no path, no trailing slash. Pattern:^[a-z0-9][a-z0-9.-]+\.[a-z]{2,}$. Examples:anthropic.com,nvidia.com. Wrong:https://anthropic.com/.category— kebab-case enum from the schema, not the display label shown inREADME.md. Convert by lowercasing the display label and replacing spaces with-:AI and Data→ai-and-dataDeveloper Infrastructure→developer-infrastructureFintech→fintechConsumer and Marketplace→consumer-and-marketplaceHealthcare and Biotech→healthcare-and-biotechIndustrials and Climate→industrials-and-climateB2B Enterprise→b2b-enterpriseOpen Source and Platform→open-source-and-platform
tags— lowercase kebab-case, same pattern asslug. At least one.ats— object with at least one provider key. Standard providers:greenhouse:<slug>,lever:<slug>,ashby:<slug>,workable:<slug>,smartrecruiters:<slug>,successfactors:<slug>workday:<host>/<site>— see the Workday section belowcustom:<slug>— fallback only when no real ATS is identifiable from the careers page source. Prefer the real provider whenever possible;customwill pass schema validation but is discouraged.
sources— at least one full URL with scheme.careers_urlis separate and also required.
For Workday the ats value is not a bare slug. It must be the full host
plus site path:
ats:
workday: nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSiteverify_live.py rejects bare-slug Workday entries. See
docs/inclusion-standard.md for the full rule.
python -m pip install -r requirements.txt
python scripts/validate.py
python scripts/verify_live.py --only <slug-you-added-or-changed>
python scripts/verify_live.py --only <slug-you-added> --require-north-america-openingsBoth must pass. validate.py checks schema, uniqueness, and README mentions.
verify_live.py hits the live careers page and ATS endpoint — this is the
authoritative reachability check, not optional.
For newly added companies, the North America opening check is also required: the company must expose at least one current opening in the United States, Canada, Mexico, an explicit North America remote region, or a remote role not explicitly limited to another region.
If verify_live.py returns a warn for a legitimate WAF block (Cloudflare,
PerimeterX), note it in the PR body with a browser screenshot. Do not
suppress the warning silently.
- One company per PR for adds; grouped fixes are fine for URL/ATS corrections.
- Branch name:
add-<slug>orfix-<slug>. - PR title: short, imperative — e.g.
Add Anthropic,Fix Stripe careers URL. - Reference the originating issue with
Closes #N. - Do not push directly to
main. Pull requests only.
- Lack a public careers or jobs page.
- Lack a current public opening in North America or an eligible remote opening.
- Duplicate an existing company under a different spelling.
- Point at a dead job board or a marketing page with no jobs.
- Use
custom:<slug>when the real ATS is identifiable from the page source.
- Bulk additions of more than ~10 companies in a single PR. Flag the issue for human review instead — the live-verify step needs careful manual inspection at that volume.
- Changes to
schemas/company.schema.jsonorscripts/verify_live.pybeyond minor fixes. Tag the maintainer. - Removing companies because of subjective signals (layoffs, news). Only remove if the careers page is genuinely dead.