# Filter syntax

The dashboard is one table and one search box. The box takes free text and `key:value` tokens,
filters as you type, and keeps the filter in the URL (`/app?q=…`), so a filtered view can be
bookmarked or shared. The same parser runs in the browser and on the server, and the page works
without JavaScript.

## Grammar

- Tokens are separated by whitespace. Double quotes group words: `"two words"`.
- **Free text** matches a substring of the repository's full name (`owner/name`), ignoring case.
  Several free-text terms must all match. A quoted token is always free text, so `"a:b"` searches
  for the literal `a:b`.
- **`key:value`** filters on a fact. Keys and values ignore case. A value may be quoted:
  `framework:"some name"`.
- **Different keys AND together:** `lang:php owner:client` means PHP repositories of clients.
- **The same key repeated ORs:** `php:8.1 php:8.2` means PHP 8.1 or 8.2.
- `key:` with no value is ignored, so a token you are still typing does not empty the table.
- An **unknown key**, or a value outside a key's fixed set, matches nothing and shows a hint under
  the box with what it expected.

## Keys

| Key | Values | Matches repositories that… |
| --- | --- | --- |
| `lang` | `php`, `node`, `go`, `bun`, `deno`, `python`, `ruby`, `java`, `dotnet`, `rust` | have a runtime of that language (`nodejs`, `golang` and `.net` work too) |
| `php`, `node`, `go`, `bun`, `deno`, `python`, `ruby`, `java`, `dotnet`, `rust` | a version: `8`, `8.3`, `8.3.12`, `22`, `1.22`, `3.12`, `21`, `8.0.300` | run that runtime with a version starting with it, by dot segment |
| `framework` | a name, optionally `@version`: `laravel`, `laravel@11` | use that framework (exact name), optionally at that version prefix |
| `deploy` | `aws`, `cloudflare`, `vercel`, `digitalocean`, `container`, `forge`, `server`, `fly`, `unknown` | deploy there (effective target, override included; not yet scanned counts as `unknown`) |
| `owner` | `mine`, `client`, `unlabelled` | belong to a GitHub owner with that label in Settings (`unlabeled` works too) |
| `eol` | `yes`, `soon`, `no` | have something past end-of-life now; nothing EOL yet but something within 90 days; neither |
| `vuln` | `yes`, `no`, `critical`, `high`, `medium`, `low` | have production vulnerabilities: at least one; none; at least one of that severity or worse |
| `vuln` | `dev`, `any` | have a vulnerability in a dev-only dependency; have any vulnerability at all |
| `org` | a GitHub login | are owned by that account or organization (exact, ignoring case) |
| `source` | `forge`, `cloudflare`, `vercel`, `digitalocean` | were matched by that platform source |
| `source` | `github-deployments` | have an environment reported by GitHub Deployments |
| `source` | `github-pat` | are reachable with the team's GitHub token for URL-added repos |
| `source` | `report` | have a runtime report from one of your servers ([server reports](/docs/sources.md#server-reports)) |
| `activity` | `stale`, `active`, `archived` | had no push for over 180 days; are neither stale nor archived; are archived on GitHub |

### Versions

Version values compare by whole dot segments, and a leading `v` is ignored:

- `php:8` matches 8.1, 8.3 and 8.4.
- `php:8.1` matches 8.1 and 8.1.2, but **not** 8.10.
- `php:8.5.12` matches only repositories whose source states that exact version. A repository
  known only as 8.5 (for example Forge without the header probe) matches `php:8.5` and `php:8`,
  not `php:8.5.12`. See [how precise a version is](/docs/sources.md#how-precise-a-version-is).
- `python:3.12` matches 3.12 and 3.12.3; `ruby:3` matches every Ruby 3; `rust:1.78` matches 1.78
  and 1.78.0.
- `java:21` matches Java 21 and 21.0.2; `dotnet:8` matches .NET 8.0 and SDK 8.0.300; `bun:1` and
  `deno:1` match their 1.x releases.
- `framework:laravel@11` matches Laravel 11.x; `framework:laravel` matches any version.

### Vulnerabilities

`vuln:` counts production dependencies only, because a vulnerable test runner is rarely urgent.
Dev-only vulnerabilities have their own values:

- `vuln:yes` and `vuln:no` are exact complements over production dependencies.
- `vuln:high` means at least one high **or critical** production vulnerability.
- `vuln:dev` means at least one vulnerability in a dev-only dependency.
- `vuln:any` means at least one vulnerability of either kind.

## Examples

| Filter | Shows |
| --- | --- |
| `shop` | repositories with "shop" in `owner/name` |
| `lang:php eol:yes` | PHP projects running something past end-of-life |
| `php:8.1 php:8.2 owner:client` | client projects on PHP 8.1 or 8.2 |
| `node:18 deploy:vercel` | Node 18 projects on Vercel |
| `lang:python eol:soon` | Python projects where something reaches EOL within 90 days |
| `java:17 java:21` | Java 17 or Java 21 projects |
| `ruby:3.2 eol:yes` | Ruby 3.2 projects running something past end-of-life |
| `vuln:critical` | anything with a critical production vulnerability |
| `vuln:no eol:no` | the quiet ones |
| `framework:laravel@10 eol:soon` | Laravel 10 apps where something reaches EOL within 90 days |
| `org:acme activity:stale` | repositories of `acme` with no push in six months |
| `deploy:unknown` | repositories Repodar could not place; set a target on the repository page |
| `source:forge php:7` | Forge sites still on PHP 7 |
| `color:blue` | nothing, with the hint "unknown filter key `color`" |
