Vol. I · No. 2crw-rw-rw- 1,3Price · 0 bytes · About
ForecastBright42 merges, 15 fixes

Dev Null News

The changelog nobody wrote

19 in brief ↓17 more stories ↓

Internals

One handle is enough

Every user in the JSON API now carries a single handle field, and who-to-follow lookups ask for handle instead of username. The duplicate is gone, with no compatibility shim.

Top storyTook the lead from Remotes learns to knock when the window is closed #1138. The API now returns only a handle. Old clients that ask by username get no error and fall back to plain suggestions, so they must switch or show wrong data. Held off 7 challengers since.

GitHub avatar of mnapoli
mnapoli, who filed the change, pictured in the contributor’s own avatar.

You curl a profile and the JSON comes back lighter. A user used to arrive twice, once as handle and once as username. Now there is one handle, and it is the same one the profile page shows in its URL. Commit authors, message senders, notification actors and who-to-follow entries all come back the same way.

Credit mnapoli, who swept the second name out of every corner of the API. Mention lists on commits, messages and previews now carry just the handle, its offset and its length, counted in characters with the @ included. The matcher still accepts handles up to 39 characters and skips anything inside code. Who-to-follow still hands you three picks and three spares, paged with round. Ask beside a profile with ?handle= and the people that profile follows come first.

The catch is the quiet part. The API checks only for handle now, so an old client still sending ?username= gets no complaint. It falls through to the plain picks, as if you had asked for nothing, and any client reading the old username field will simply find it missing.

In Brief

FixesClicking the quoted excerpt in a quote notification now opens the commit, matching the rest of the row instead of swallowing the click. #827

FixesThe commit status badge popover now opens 8px below the badge, so resting the pointer near its edge no longer makes it flicker open and closed. #858

FeaturesContributors on the about page who have a profile now link to it with a hovercard, while everyone else still links to GitHub. #870

Fixes"End stream" in the profile menu now shows a crossed-out radio instead of a plain square, so it reads as the off switch to "Go live" rather than an empty checkbox. #882

FixesSeeded dev accounts now get hyphenated usernames like jane-doe instead of jane.doe, so local data matches GitHub's username rules. #914

FeaturesCopy link and Report now surface only on the commit or reply you hover, like the delete icon, and stay put for keyboard focus and touch screens. #940

FixesThe Developer Achievements dialog's close button now floats in a dark circle above the panel, clear of the rank badge and visible on small screens. #974

FeaturesProfile previews now show the person's local time under the bio, like 8:14 AM (UTC +02:00), when they have turned on sharing their timezone. #1014

FixesThe graph rail's end dot now lines up with each commit's actions row, and the reply box opens on its own line below it. #1135

FixesReactions that arrive at the same moment now stay capped at 12 per person per message, because each new emoji is counted again just before it is saved. #1142

FixesTimed-out users can no longer set a live stream link, though they can still end an active stream. #1146

DocsThe Mac app page now invites visitors to contribute through a link to the app's GitHub repository. #1155

InternalsEach user's GitHub identity now lives in its own profile row, and the login is called a handle in code, URLs, and exports. #1156

InternalsGitHub handles, names, avatars, bios, locations, websites and sync times now live only on profiles, every user must have one, and the copies on user records are gone. #1157

FixesChat threads hold their reading position when the last pinned message is unpinned, instead of jumping about 36 pixels. #1165

FixesFreshly arrived commits now fade their highlight over 1.4 seconds, and only fresh rows carry the slow transition, so hovering a commit no longer twitches. #1172

FixesThe suggested-users API's username filter and the dismiss endpoint now resolve handles from profiles, so both work again after handles left user accounts. #1178

FixesThe about page no longer crashes while listing contributors who have a profile, and it links each one by their current handle instead of a stale username. #1183

InternalsThe followers, following, mutuals, and followers-you-know lists now carry one of four fixed labels instead of a plain string, so a mistyped value can no longer slip through. #1194

5 routine merges sent to /dev/null

Features

Remotes learns to knock when the window is closed

A new Off-site notifications switch pushes a quiet alert to your browser or installed app, even with the site shut. It stays off until you ask, and it never shows who wrote or what they said.

Open Settings, then Remotes, and the alert list has grown to three switches. Below On-site notifications, which is on, sits Off-site notifications, which is off, and Notification sound. Flip the new one, say yes to the browser's permission prompt, and close the tab. Ten seconds after someone messages you, a quiet banner appears. It reads, "/dev/null · Remotes. You have a new message in Remotes." Click it and you land in your Remotes inbox.

Credit goes to the contributor who wired a real push pipeline behind that switch. Every new unread message queues one delivery per recipient. Each delivery is held 10 seconds and rechecked before it leaves. The message must still be in the conversation, still unread, not muted, not blocking the sender, and Remotes must still be on. Only then does the server sign an empty request and hand it to the browser's push service, so Google, Mozilla and Apple never see a word of the message. Each account can enroll 20 browsers or installed apps. The 21st is refused with a plain error, and a lock stops two tabs from racing past the limit. Failed sends retry three times, and the banner names no sender and shows no preview.

There is one catch. The switch needs your browser's shared locks, the mechanism that keeps two tabs from enrolling at once. Where those are missing, the Off-site switch sits greyed out. On a phone or tablet, you must add /dev/null to your Home Screen and enable it from the installed app. A plain Safari tab never gets the option.

Features

Profiles now name the followers you know

Open someone's profile and it now names the people you follow who follow them too, most-followed first. The rest are a click away.

You land on a profile you don't know and, right under the follower counts, a small row of avatars appears with a sentence. The sentence names two handles you recognise, then says how many others you follow who follow this person too. The handles open those profiles. The avatars, and the count, open the whole list, which also gets its own tab between Followers and Following, shortened to "You know" on phones. You have to be signed in and looking at someone else to see any of it.

Credit ashkesarmaa, who crossed the profile's followers with the people you follow, using the follow records already there, with no new table or migration. The preview fetches three, shows three little avatars, but names only the two with the most followers. The sentence counts every one of them. The list comes 30 at a time, each row with its own Follow button.

One catch. The profile names the best-followed, but the list behind it runs newest follow of that profile first, like the Followers tab. The handle you just read may sit pages down among the 30-at-a-time rows, so click through expecting a different order.

Features

Search learns to do, not just find

Type "bug", "feature", "commit" or "go live" and the action rises above your results. Press Enter and you are already in the right dialog.

You hit the search key, type bug, and there it is above the results under Actions. The action is Report a bug. Press Enter and the composer opens already in bug mode, ready to file the issue. Type co and no action appears. Type comm and Write a commit takes the top slot instead.

Credit goes to simonhamp, who taught search to do five things as well as find them. You can write a commit, request a feature, report a bug, go live, and end a stream. The matcher needs three letters and only fires while your search is the start of one of its words, so "commits about caching" stays a search. A bare slash offers the same /feature and /bug commands as the composer. Go live gives you a stream link box and a slider from 1 to 12 hours, preset to 2. Signed-in people only. The developer pickers in chat leave all this out.

One catch. Come in through bug or feature and the header over the box still reads "Write a commit", even though the box is set to open an issue.

Features

Your GitHub README now shows up on your profile

Profiles gain a third tab that renders the README from your GitHub profile repo. Formatting, links and GitHub-hosted images come through. Scripts, styles and classes do not.

Open any developer's profile and click README, the third tab beside Commits and Replies, and their GitHub profile page appears without leaving the site. Headings, badges, tables, centered banners and all come through. Links open in a new tab. Nothing is fetched from GitHub until you ask for that tab.

Credit goes to hbenabdallah, who taught profiles to read the repository GitHub names after the developer. The server asks GitHub for the rendered page, then runs it through a fixed list of tags. Scripts, styles, classes and ids go. Images survive only from five GitHub-owned hosts, and links must be http, https or mailto. One fetch is kept for a day, or four minutes when the README holds uploaded images whose signed links expire. A GitHub timeout is remembered for five minutes so an outage does not hammer the API.

One catch. If someone opens your README tab while you have no README, the server remembers "no README" for a full day, so the one you add this morning may not appear until tomorrow. Errors clear in five minutes. An empty profile does not.

Fixes

Time's up for the issue window

People in timeout used to slip bug reports and feature requests past the gate. Now those drafts get the same amber dialog as everything else, reason and time left included.

You've got a bug to report. Type /bug in the commit box, which turns your draft into a bug report, paste the steps, hit send, and instead of a GitHub error toast you get the amber hourglass. You're in timeout. Here's the reason, and here's how long is left. Your draft stays put, still an issue, ready for another try.

Credit goes to sulimanbenhalim, who put bug and feature drafts behind the same lock as replies and remote messages. The server checks your timeout before it checks the 10-issues-a-day limit, and turns you away with the reason and the time remaining, rounded up to the minute, or to the whole hour once more than a day is left. Open ten issues in a day and you still hit the old wall.

One catch. That dialog is shared with replies and remotes, and its wording hasn't caught up. It tells you that you can't commit, reply, or send remotes, and never mentions issues. You get the right reason and the right countdown, but you have to infer that bug reports are on the list too.

Features

Codeberg and merge-request links get their icons

Paste a Codeberg or merge-request link into a commit and it now shrinks to the forge's icon plus owner/repo, with the issue number intact. Merge requests keep their own marker before the number.

You type a commit, flip to the preview, and the long GitLab URL you pasted comes back as the tan GitLab mark and the merge request numbered 42 in gitlab-org/gitlab. Do the same with Codeberg and a pull request reads forgejo/forgejo#42, icon and all.

Credit goes to zangetsu02, who replaced the lone GitHub matcher with a small table of forges. Each row holds the host, owner rule, item paths, the mark written before the number, and an icon. Three forges sit in it now. They are GitHub, GitLab and Codeberg, each with its own list of reserved first paths (7 for GitLab, 12 for Codeberg) so explore/projects and user/login stay ordinary links. Owner and repository names run to 100 characters on the two new forges, item numbers to 10 digits with no leading zero, and GitHub's existing tests pass unchanged.

The catch is that it matches on domain alone. A GitLab project inside a subgroup, like group/subgroup/project, stays a bare URL, and so does anything on a self-hosted Forgejo or Gitea server, because the code has no way to tell those apart from the host name.

Features

Who to follow follows you to the API

Signed requests can now ask who to follow and get the same six picks the web shows. You get three to display and three spares. Turn a round for the next page, or pass a profile or commit for context.

You sign a request and ask for six names. Back come three to put on screen and three spares, each with a follower count, the number of people you follow who follow them, and a flag saying whether they follow you. Dismiss one and a spare slides up in its place. Nobody in the list is followed yet.

Credit goes to Taldres, who wired signed requests to the same suggestion engine the web runs. It mixes people your follows already follow with a popular pool drawn from the 20 most-followed accounts, and only ever suggests someone who has posted a top-level commit. The picks hold steady all day, seeded from your account id and the date, then reshuffle tomorrow. Turn the round number for the next page. Past the last page it loops.

Ask beside a profile and that developer's follows come first. Ask beside a commit and the thread's other posters do. Send both and you get a 422, and a commit you can't see answers "That commit is no longer available." Muted and blocked people stay out.

One catch. Marking someone not interested is a one-way door. The call returns 204 and they never appear again, but there is no call to undo it and no list of who you dismissed.

Features

Mutuals get a tab for people you follow who follow you

Profiles grow a Mutuals tab beside Followers and Following. It lists the people a profile follows who follow back, 30 at a time.

Open a profile, click Followers, and look along the tab strip. Beside Followers and Following there's a new one called Mutuals. Click it and you get the familiar list, avatar, name, handle, a line of bio, and a Follow button on every row, but only for people that profile follows who also follow it. When there's nobody, the empty state deadpans "Fatal. No mutuals yet."

Credit goes to kachelle, who built the list from the follow records the site already keeps. Take everyone the profile follows, keep only those with a follow pointing back, and hand back 30 per page as you scroll. Each row knows whether you follow that person, so the button is right. Guests can browse it too. Across a block in either direction, the page is simply not found.

One catch. The sort runs on when the profile followed each person, not when each one followed back, so a mutual who returned the favour this morning can sit far below someone they followed last week.

Features

GitHub links learn GitHub's shorthand

Paste a GitHub pull request, commit, release, or file link into a commit and it now shows the way GitHub writes it. You get owner/repo#42, owner/repo@4fa008f, or the file's own name. The full URL still rides along in the text.

You paste a pull request link into a commit and hit preview. Back comes the owner/repo shorthand, octocat in front, the number where your eye expects it, no ellipsis.

Credit jubianchi, who taught the linkifier to walk GitHub's paths one segment at a time instead of matching the whole URL at once. Commits and releases read as the repo plus an at-sign and a short hash or tag. Commit hashes get cut to seven characters whether you paste seven or all 40. Comparisons show the two branch names with three dots between them, and a comment or review marker adds a word after the number. Profiles drop the repository and leave just the octocat and taylorotwell.

Files and folders are the freshest trick. A link into a file becomes the repo name, a colon, the file's own name, and a line range. A folder becomes the repo name, a colon, and the folder's last name with a slash. The branch and full path stay in the link's title and are read aloud to screen readers. The full URL also stays in the text, invisible but copyable. Forty-eight of GitHub's own pages, from dashboard to pricing, stay URLs so they aren't mistaken for accounts.

One catch. When a branch name holds a slash, as in feature/login, a file or folder link hands that branch to the path reader anyway. The folder comes out named after the last segment instead of its real name, though the link still lands in the right place.

Fixes

Unread badge counts chats, not chatter

The little number beside the chat icon no longer climbs with every message. Three pings in one conversation now add one to the badge, not three.

Three messages land while you're away, all in the same chat. You come back, glance at the sidebar, and the unread badge has moved by one. Open the inbox and that conversation's row still reads 3 ahead, but the count on the Remotes header reads 1. Nothing in settings changed. The badge simply stopped counting messages.

Credit goes to kachelle, who taught the count to count conversations. The server now tallies distinct conversations holding unread messages instead of every message, so each chat adds at most one. Two friends write in, three notes from one and two from the other, and the badge shows 2 instead of 5. Waiting requests still ride along in the same number, and the dock rechecks every 15 seconds, or every 6 with a thread open, subtracting the chat you're already reading.

There is a catch. Rows and badge now speak different languages. A row still totals messages, so one chat can announce 8 ahead while the badge says 1, and pending requests can push the badge above the number of unread chats. When the two numbers disagree, the badge is the one counting conversations.

Features

Terms agreed, and now on file

The iOS app can record the moment you accept the terms and privacy policy, and the version you agreed to. Say yes once and the server keeps the receipt.

Open the app for the first time since the update and it asks you to accept the terms and privacy policy. Tick the box and the server writes down the moment you did. Come back later and it stops asking, because the account it hands to the app now carries the date you agreed and a plain yes-or-no for whether that counts.

Credit goes to shanerbaner82, who wired the tick to the database and rewrote the fine print for Apple's reviewers. The version in force is a single moment, 25 October 2026 at midnight UTC, and the server accepts only that exact one. Send any other and it answers with a 422, so an old build cannot agree to wording it never displayed. The sign-in call can carry the version too, and every answer about the signed-in user now reports the version, your acceptance date, and whether you are current. The published terms gained zero tolerance for abusive users, Report, Mute and Block, action on reports within 24 hours, bans that survive an Apple sign-in, and the usual Apple clauses.

There is one catch. This is a record, not a gate. Nothing on the web or in the API checks your acceptance before letting you post, and the web sign-in page still has no checkbox. Everyone already on the service starts with a blank date, so the app asks them once.

Features

Org chat gets pins that stay put

Maintainers can pin up to 25 messages in an org, and a bar at the top of the thread shows the count and the newest one. Everyone in the org sees them, even people who joined without the history.

Open an org thread and a thin strip rides over the top of the messages. It holds a pin, a count in mono type, and the name and first line of the newest pin. Press it and a panel drops down with all of them, newest first, each with its author and time.

Credit simonhamp, who gave every message a pinned time and taught the thread to read it. The list comes back newest first, a maintainer can keep 25 at once, and the count is checked again after the org is locked, so two maintainers grabbing the last slot can't make 26. The loser just sees the pin refused. Pin an old message and it opens to everyone in the org, history or not. Images load, voice notes play, reactions and replies work.

Long pins stop at three lines in the panel, with a Show more button. The first pin asks "Pin for the whole org?" and won't ask again once you tick the box. The app gets matching pin and unpin calls, though it has no buttons for them yet.

One catch. A member whose history starts after a pinned message can react to it while it stays pinned. Unpin it and the message leaves their view, but the reaction they left stays behind with no way to take it back.

Features

Scheduled commits get a head start

A new button on the scheduled commits page sends your post into review before its scheduled hour. The old Cancel button is now a trash can.

Open the scheduled commits page and every waiting row now carries a Commit now button beside a small trash can that replaced the old Cancel button. Hover the can and a tooltip says Cancel. Press Commit now and the button locks and reads "Committing…", then the row settles into Submitted for review with its body still in place, and the rest of the list keeps its order.

Credit goes to kachelle, who gave the scheduler a manual override. The button sends a commit through the usual review process ahead of time, and the body, poll, images and link preview all travel with it, landing as a pending commit like any other. Under the hood, one conditional update claims the row only if it is unsubmitted, uncanceled, and its author is neither timed out nor banned. The work runs in a transaction retried five times, so a double press cannot make two commits. The list still refreshes every 30 seconds, and you can hold up to 10 schedules at once, up to 30 days out.

One catch. Commit now spends from the same budget of 10 commits a minute as ordinary posting, so on a busy minute the button answers with a "Slow down" toast and your commit goes back to waiting for its scheduled hour.

Fixes

A late unsubscribe now stops queued mail at the door

Opt out of an admin email after it's already queued and it no longer arrives. Banned accounts get the same silence.

You click unsubscribe on Monday's admin note and get back to work. Tuesday's copy of that same note, queued before you clicked, never shows up. No bounce, no apology, no filter rule to write. The queued email looks at your account and stands down.

Credit goes to Akiyo974, who made each queued admin email check its recipient once more at delivery. Admin mail leaves in batches of 500, one job per person, carrying only a user id, so the address and unsubscribe link are rebuilt when the job runs. Akiyo974 added a look at that freshly loaded record. If the unsubscribe or ban timestamp is set, the job returns before the mailer sees it. A test email addressed by hand still goes through. Each job gets three tries, with 60- and 600-second backoffs between them.

There is one catch. The confirmation you see after sending counts everyone the audience picked when you hit the button, not everyone who actually receives it. Opt out afterward and you still sit in that number, while the skipped job finishes quietly and reports success.

Features

The conversion rate gets a device divide

The Growth page now breaks the conversion rate down by phone, desktop and tablet, with the visitor and signup counts behind each one. A slide in the overall rate finally tells you whether the mix shifted or one device got worse.

You open Growth and leave the dates at their default 30 days. Below the funnel, past the daily charts, a new panel lays out a tile for each device type Fathom reports. Those are usually phone, desktop and tablet. It then adds one for all devices. Ordered by visitors, busiest first, each tile gives a rate to one decimal and the raw counts behind it, so you can see how many signups came from how many visitors.

Credit goes to mnapoli, who taught the funnel to ask Fathom for device totals. It requests the unique people behind the visit event and the signup event, grouped by device, then divides one by the other for each device. Fathom's answers sit in a five-minute cache, and the all-devices tile still comes from the funnel's overall rate.

One catch. A signup is filed under the device it happened on, not the device the person visited from. Read on a phone and sign up on a laptop, and your visit stays in the phone column while your signup lands in the desktop column. Phones then look worse at converting than they are, and desktops look better.

Features

Your GitHub crowd shows up in onboarding

The follow step now opens with a receipt from GitHub. It shows how many people you already follow here, how many already follow you, and their faces. The heading changes to match, so you stop feeling like you start from zero.

You sign in with GitHub for the first time, click through setup, and land on the follow step. Above the usual suggestions sits a hairline card stamped imported from github.com/yourhandle. Two big mono numbers tick up from zero while little avatars pop in one at a time, each ringed in its own lane color, five faces and a +4 for the rest. The heading no longer says "Follow a few developers." It says you already follow nine.

Credit goes to mnapoli, who taught the step to show the import's work. The page checks back every 1.5 seconds while the import runs right after sign-in, and stops after 15 seconds if it never lands. A follow counts as imported if it was made in the ten seconds before the import stamped its finish time. The welcome bot is filtered out. Followers get their own number and their own faces, and the suggestions reload once the import lands so you aren't offered people you already follow.

One catch. The row for people you follow on GitHub who aren't here yet, with its copy-an-invite button and X post, isn't wired to anything. Pending follows aren't stored, so that count is zero everywhere except local development, where it comes from a number you type into the URL. Everyone else sees the faces and no invite.

Features

A join sheet rises on phones

Signed-out phone visitors now get a card at the bottom of every page explaining /dev/null, with a Join with GitHub button within thumb reach. Close it and the tab bar comes back.

Open /dev/null on your phone while signed out and, a moment after the page settles, a card slides up over the tab bar. It reads "you're reading /dev/null" above "Only developers post here," then lists three things. Every account is a GitHub account, you start out following the people you already follow on GitHub, and posts are commits of plain text about what you're building. A full-width Join with GitHub button sits where your thumb already is.

Credit goes to mnapoli, who built the sheet into the app's shared layout, so every page carries it. Three bullet lines, one button 48 pixels tall, a 300-millisecond slide up, and a shadow to lift it off the feed. It hides itself at 768 pixels and wider, and ducks out of the way while the keyboard is open.

One catch. The ✕ only silences the sheet for the tab you are in. Open a fresh tab and it slides up again, and if your browser blocks per-tab storage, it comes back on every single page.

Who Filed

  1. kachelle11
  2. mnapoli8
  3. xHeaven3
  4. Akiyo9743
  5. sulimanbenhalim3
  6. Taldres2

Merge Market

SectorVolLines
Features17+9,598
Fixes15+417
Internals6+885
Chores3+411
Docs1+10

Back Issues