Maintainer Mode
Sign in with GitHub
Work in progress. Maintainer Mode changes every day: pages, numbers and links can change or break. Tell us what is wrong or missing.

Your own view

All docs · The source is docs/personal.md.

What Maintainer Mode shows for you: what you maintain, what you watch, and the packages of your own system.

The menu

Every page has four tabs: Home, Review, Packages and nixpkgs. Your own pages are in a menu at the top right. Sign in, and the menu shows your login. When you have unread events, the header also shows their number. Push the number to open your inbox. The menu has these items:

On these pages, no tab is current. The menu marks the current page.

Only you see /inbox and the pages under /me. The server sends each answer there with Cache-Control: private, no-store. It does the same for /packages when you are signed in. /u/<login> is public, and it is the same for every viewer. It has two tabs: Record and Maintains. Search for @login on /packages to open it.

Needs you

Sign in, and the home page starts with Needs you. It is a list of open items. Each item is one thing that waits for you. Each item has one primary action: push its title to open its page. The most urgent item comes first. Only you see the list.

The list does not show what happened. The inbox does that. The list shows what is still open. When the cause of an item is gone, the item leaves the list.

The items

OrderCauseIt opens
1An advisory on a package of your latest machine report. The CVSS score is 7 or more, the EPSS chance is 10% or more, or CISA says that attackers use it.the package page
2Your open pull request got a review, a change request or a review comment from another person after your last push or comment.the pull request
3Your open pull request is blocked: its checks fail, it has a merge conflict, or it has an approval on its last commit for 3 days or more and is not merged.the pull request
4Your open pull request has had no review for 7 days or more. The item names the maintainers of the files to ask, at most 5.the pull request
5An open pull request in the review queue changes a package of your machines or a package you maintain. Your review on its last commit removes it.the pull request
6A package you maintain has a newer upstream release, or its last Hydra build failed.the package page

In cause 1, the worst severity comes first, then the highest EPSS chance. In cause 2, the newest review comes first. In causes 3 and 4, the oldest comes first. In causes 5 and 6, the order of your packages applies: the packages of your machines come first, then what you maintain. A draft pull request gets cause 2, and cause 3 for failing checks or a merge conflict.

The server uses only data that it already has. These signals are not in the list:

Moods

The chips above the list select a mood. Each chip shows its count.

ChipAddressWhat it keeps
All/?mood=allall items
My pull requests/?mood=minecauses 2, 3 and 4
My machines/?mood=machinescause 1, and cause 5 for the packages of your machines
Review/?mood=reviewcause 5
Maintain/?mood=maintaincause 6, and cause 1 for a package you maintain

A cookie (mood) keeps your last mood for one year.

Snooze

Push "Snooze" to remove an item from the list. The item comes back when its state changes: a new review, a new push, a new advisory, a new release or a new cause. The server keeps the key of the item and a fingerprint of its state. It does not keep more.

Next

"Start" opens the first item of the mood. On the page of an item, "Next" opens the next item of the same mood. Snoozed items are skipped. The address is /needs/next?mood=<mood>&from=<key>. When no item is left, it goes back to the home page. The page of a pull request and the page of a package show "Next" when you are signed in. They also show "Snooze" when the page is an open item.

The footer of the list shows how many items left the list since you signed in, for example "2 done this session". There is no score, no streak and no leaderboard here.

Keys

On the list and on the pages that "Next" opens, you can use these keys:

KeyWhat it does
jselect the next item
kselect the previous item
o or Enteropen the selected item
nopen the next item
ssnooze the selected item

The keys do nothing while you type in a field. Everything also works without JavaScript.

The JSON API gives the same list at GET /api/v1/needs. See api.md.

Your packages

Signed out, /packages shows the catalog of nixpkgs: a search box and the directories. Signed in, it shows a filter bar on top. Each filter shows its count. The search box filters the list of the current filter.

FilterAddressWhat it shows
Mine/packages?filter=mineall of the rows below, in one order (the default)
On my machines/packages?filter=machinesthe packages of your latest machine report and of your scanned flakes
I maintain/packages?filter=maintainwhat nixpkgs names you as a maintainer of, and "Watch everything I maintain"
I watch/packages?filter=watchwhat you watch, a form to watch more, and a "Stop watching" button on each
All of nixpkgs/packages?filter=allthe catalog, as a visitor sees it

A search with no filter, such as the search box of the home page, goes to All of nixpkgs.

The order. Mine puts the packages of your machines first. Then it puts what you maintain, then what you watch. In each group, the rows that need attention come first: an open advisory, a newer upstream release, a failed Hydra build or an open pull request. Then the highest risk score comes first. Each row shows why it is in the list: "on your machines", "you maintain" or "you watch". It also shows its health flags. Each filter shows 50 rows. "Next page" adds ?after=<number>, the count of rows on the previous pages.

The Hydra flag shows only a build that a package page read in the last hour. The list itself never asks Hydra.

No machine report yet. Then the bar shows the step "Upload the packages of your machines" in place of the machines filter. It links to /me/settings#upload. When you have a report, the machines filter shows the time of the latest report, the button "Delete my report", the list and the panel of public flakes (see below).

The home page uses the same order. Its section "Your packages that need you" shows the rows of Mine that need attention. It links to /packages?filter=mine.

Old addresses. These addresses redirect:

Old addressNew address
/me/packages?filter=mine
/me?tab=inbox/inbox
/me/inbox/inbox
/me?tab=maintain/packages?filter=maintain
/me?tab=watch/packages?filter=watch
/watch/packages?filter=watch
/me?tab=machines/packages?filter=machines
/me/sets/packages?filter=machines

Profiles

/u/<login> is the public profile of one person. Every login on the site links to it. The header shows the GitHub avatar, a link to the GitHub account, and these facts when the data has them:

The page shows facts only. It has no score and no ranking.

TabWhat it shows
/u/<login>Overview: the open pull requests, the merged or closed pull requests of the last 60 days, and the directories of the recent pull requests
/u/<login>?tab=reviewsthe review record
/u/<login>?tab=maintainswhat nixpkgs names the login as a maintainer of

The Overview tab shows the review state, the age and the checks of each open pull request. Pull requests with no review for 7 days or more come first: a review helps there. When you look at your own profile, a link goes to your private pages under /me. The profile itself shows no private data.

Settings

/me/settings is one page with these sections. The links at the top go to each section.

SectionWhat you set
#emailthe kinds of events that the unread count and the email digest show, and the digest address
#feedthe private link of your Atom feed
#uploadthe upload token for maintainer-mode submit
#llmthe LLM choice (see actions.md)
#mcpthe MCP token
#workflowsthe setup checklist and the repositories where "Review in CI" and "Update with nix-update" run
#tagsthe path prefixes that the For you tab of /review adds
#goalyour weekly goal
#startshow or hide the Get started card

Get started

The home page shows a short introduction to visitors who are not signed in. It names the three ways to use Maintainer Mode. It links to the nixpkgs contributor guide (CONTRIBUTING.md). Press "Hide" to remove it. A cookie keeps it hidden for one year.

After you sign in, the home page shows the Get started card. It is a checklist. Each step shows your real state: done, to do, or optional.

  1. What you maintain, in the "I maintain" filter of /packages. Watch all of it in one step.
  2. What you watch. Watch a package, a module or a directory.
  3. The review queue for you, on /review.
  4. Notifications. Make your private Atom feed in /me/settings#feed.
  5. Your system. Upload the packages of your machines in /me/settings#upload. They then come first in /packages.
  6. Actions. Follow the setup checklist in /me/settings#workflows.
  7. LLMs. They are off by default. Turn them on in /me/settings#llm.
  8. The nixpkgs guides: CONTRIBUTING.md, pkgs/README.md, nixos/README.md, maintainers/README.md and the Nixpkgs manual.

If you maintain nothing, the first step changes. It sends you to the pull requests with no maintainer on /review, with a checklist for a first review. It also links maintainers/README.md.

Press "Hide" on the card to remove it. Your menu shows "Get started" until you do. To show the card again, use /me/settings#start. Only you see the card.

What I maintain

The "I maintain" filter of /packages lists the packages and NixOS modules whose meta.maintainers names you, or whose meta.teams names a team you are in. Each row carries the same health flags as a page. "Watch everything I maintain" adds every row to what you watch. The list comes from nixpkgs; change it there.

The Maintains tab of /u/<login> lists the packages and NixOS modules whose meta.maintainers names the login, or whose meta.teams names a team the login is in. Each row carries the same health flags as a page. The highest risk score comes first. The list comes from nixpkgs; change it there. /u/<login>/maintains is public.

What I watch

Watch any package, module or area from its page, or by name in the "I watch" filter of /packages. Watch everything you maintain in one step in the "I maintain" filter. The "I watch" filter shows each item with its flags, and a "Stop watching" button.

Review, for you

/review is the one place to review. It has five tabs, and each tab shows its count:

TabAddressWhat it lists
For you/review?tab=foryoupull requests that touch your machines, what you maintain, own, changed, tagged or watch
No maintainer/review?tab=unownedpull requests with no maintainer, team or ci/OWNERS line on their files
Bumps/review?tab=bumpsopen version bumps (see health.md)
All/review?tab=allevery pull request in the queues that is not ready to merge
Ready to merge/review?tab=readythe ready-to-merge queue, and the lists for committers (see below)

Sign in, and /review opens on For you. For you looks at the packages of your machines, meta.maintainers, meta.teams, ci/OWNERS, the paths you changed this year, your tags, and every package, module or directory you watch. It uses the order of your packages: pull requests that touch the packages of your machines come first, then those on what you maintain, own, changed or tagged, then those on what you watch. In each group, the oldest comes first. Signed out, /review opens on No maintainer, and For you is not shown.

Each tab shows 50 rows. "Next page" adds ?after=<number>. On most tabs, it is the number of the last pull request on the page. On For you and Ready to merge, it is the count of rows on the previous pages, because these tabs are not in number order. /merge, /committer and /bumps redirect to their tab.

The JSON API takes GET /api/v1/prs?queue=foryou&login=<login>. The MCP tool prs and the CLI (maintainer-mode prs --queue foryou --login <login>) take the same names. Your subscriptions are private. They count only when your own session or your own MCP token asks for your login. In all other cases only your public area counts. The API never reads your machine report, and it keeps the number order. See api.md.

Your progress

/me/progress shows your own review record. Only you see it. It never shows the numbers of another person. There is no leaderboard.

The page counts the synced data only: the last 60 days and every open pull request. A small box on /review shows your week, your streak and your goal. Your menu links to the page.

Notifications

The inbox. /inbox shows the events of your Atom feed: what happened in the last 30 days to what you watch and to your package set. The newest event comes first. Filter the list by kind (pull request, issue, advisory, release) or by subscription. "Mark all read" marks every event as read. Only you see your inbox.

The unread count. The header shows the number of unread events. The server counts them after each sync pass, and when you open the inbox. In /me/settings#email, choose the kinds that the count includes.

The email digest. This is off by default. It works only when the operator sets up SMTP (see operations.md). Enter an address in /me/settings#email to get the digest. The server sends at most one email a day. The email lists the unread events of your chosen kinds since the last digest. "Send me a test email" sends one email, at most once in 10 minutes.

Confirm your address

The server sends no digest to an address that you did not confirm. When you enter or change the address in /me/settings#email, the server stores it as pending. The server then sends one confirmation email to the address. Open the link in that email in the next 24 hours. Push the Confirm button on the page that opens. The settings page then shows "confirmed". A link scanner can open the link, but it cannot confirm the address. Only the button confirms it. If the link is too old, push "Send the confirmation email again" on the settings page. You get at most 3 confirmation emails in 24 hours. A test email goes only to a confirmed address. You can send at most 3 test emails in 24 hours, with 10 minutes between them. Addresses that you saved before this change are pending. Confirm them again to get the digest.

My package set

Tell Maintainer Mode which nixpkgs packages you run, and your feed tells you when one of them gets an advisory or a new upstream release. The set is private. Facts about nixpkgs are public; facts about your machines are not.

You evaluate your own tree on your own machine. By default, the server never evaluates it. Three client commands do the work:

maintainer-mode scan --flake . --output nixosConfigurations.<host>.config.system.build.toplevel
maintainer-mode --server https://<host> export --out report.json
maintainer-mode submit --to https://<host> --token-file ~/.config/maintainer-mode/upload-token

To save the list for an offline export:

curl --compressed -o index.json https://<host>/api/v1/packages/index
maintainer-mode export --index-file index.json --out report.json

How the client filters. The public list gives the pname and the version of each attribute of the server's current nixpkgs index. The client keeps a closure entry only when its name is a public attribute or a public pname. It also tries the name in lower case and python3Packages.<name>.

What leaves your machine. The strict report has only these fields:

The name of the scanned tree never leaves your machine. The client sends no path, no store hash and no private name. The local report uses the nixfresh report format, schema 1.

The upload token. Make it in /me/settings#upload. The server shows it once and keeps only its SHA-256 hash. A new token replaces the old one. One button revokes it.

What the server does with a report.

CodeMeaning
202stored; the answer gives the kept and dropped counts
400not a strict report; the error names the problem
401no token, or an unknown token
413more than 16 MiB, or more than 50,000 packages
503the nixpkgs index is not built yet

The list. The "On my machines" filter of /packages shows the packages of your latest report and of your scanned flakes. Each row has the health flags of a package page: advisories, a newer upstream release, a failed Hydra build, open pull requests and open issues. The rows that need attention come first. These packages also come first in Mine, on the home page and in For you on /review.

Alerts. Your private Atom feed (see above) also gets, for each package in your set, a new advisory and a new upstream release. It does not get the pull requests and issues of the set, because a closure has thousands of packages.

A public flake, scanned by the server. This is off by default. When the operator turns it on, the "On my machines" filter has a form for a public flake reference (github:OWNER/REPO, github:OWNER/REPO/BRANCH, or an https:// tarball) and an output. After each nixpkgs index, the server scans the output again. It keeps the result with the rules of an upload: the same public-list filter, the same index filter and the same 90-day rule. The server stops the scans of a person who has not opened /packages signed in for 90 days.

docs/rescan.md has the threat model, the sandbox, the limits, and why the feature is off by default.

For committers

The tab Ready to merge of /review shows what waits for a person with merge rights. Everyone can see it. A committer who signs in also sees the section In your areas at the top. The home page of a committer links to the tab.

Who is a committer. Maintainer Mode counts a login as a committer when one of these is true:

/api/v1/status shows the counts. No page or API lists the logins.

The sections.

SectionWhat it shows
In your areasonly for a committer who signed in: the ready-to-merge queue in your areas and in what you watch, 5 rows. Only you see it. Its id is yours.
Ready to mergethe ready-to-merge queue: 20 rows on the first page, then 50 on each page. Authors with more review credit come first.
Approved by a maintaineran approval on the current head by a login in the meta.maintainers or meta.teams of a package or module that the pull request changes
Security fixesthe label 1.severity: security, and ready
Backportsa release-* base branch, and ready
Waiting longestready, oldest approval first

In the last three sections, "ready" means that the checks pass, that there is no known conflict, and that the current head has an approval. The pull request does not need credit. Each row says why it is on the list. The last four sections put the longest wait first. They and In your areas show on the first page only, with 5 rows each. "see all" opens the full section, 50 rows on each page: /review?tab=ready&section=<id>. The ids are maintainer_approved, security, backports and waiting, as in the API.

Maintainer Mode never merges. Each row links to GitHub, and you decide. Read the nixpkgs contributor guide for how to review and merge.

The API. /api/v1/prs?queue=ready gives the same lists without In your areas. It is the same for all callers, because your subscriptions are private.