Updates, ideas, and inspiration from GitHub to help developers build and design software.
Dungeons & Desktops: 10 roguelikes that never die (because their communities won’t let them)
Roguelikes don’t die. They fork, mutate, get argued over, rewritten, abandoned, and revived again. Sometimes all at once. The post Dungeons & Desktops: 10 roguelikes that never die (because their communities won’t let them) appeared first on The GitHub Blog.
GitHub Copilot individual plans: Introducing flex allotments in Pro and Pro+, and a new Max plan
Starting June 1, our lineup of individual plans will update based on your feedback. The post GitHub Copilot individual plans: Introducing flex allotments in Pro and Pro+, and a new Max plan appeared first on The GitHub Blog.
We’ve heard your questions about whether the included usage in each GitHub Copilot plan will go far enough when we transition to usage-based billing on June 1st. Longer agent runs, multi-step work, and more capable models will all put pressure on the usage amounts detailed in our original announcement. We’re updating the individual lineup based on that feedback. Pro and Pro+ will include more total usage at the same price through a new flex allotment, and we’re introducing Max, a new plan for sustained, high-volume Copilot work. What’s included The individual Copilot lineup will span Free, Pro, Pro+, and Max, with usage-based billing across all plans. Free will continue to include a limited number of code completions each month, plus limited chat and agent usage with auto mode. For paid plans, monthly included usage comes in two parts: Base credits: matched 1:1 with your subscription price. These never change. Flex allotment: variable additional usage on top of your base. Flex allotments will vary over time. Below are the individual plans as of June 1, 2026: Plan Price Base Flex Total included usage Pro $10/month $10 $5 $15 Pro+ $39/month $39 $31 $70 Max $100/month $100 $100 $200 How it works Your base credits are used first. If you go beyond your base, the flex allotment is applied automatically at the same rates across your IDE, github.com, and the CLI. You don’t need to turn anything on or manage a separate bucket; your dashboard will show what’s available and what you’ve used. And if you use everything included in your plan, you can purchase more usage and keep going. Code completions and next edit suggestions remain unlimited on paid plans and don’t consume credits. Why flex can change The flex allotment is a variable part of your included usage; it is designed to adapt as the economics of AI evolve, including model pricing, new models, and improvements in efficiency. Your base credits, which are 1:1 to your subscription price, will always stay the same. What to do Nothing. If you’re on a monthly Pro or Pro+ plan, the additional usage lands automatically on June 1 when you migrate to usage-based billing. For more information, read the docs > The post GitHub Copilot individual plans: Introducing flex allotments in Pro and Pro+, and a new Max plan appeared first on The GitHub Blog.
Dungeons & Desktops: Building a procedurally generated roguelike with GitHub Copilot CLI
Learn how one Hubber used GitHub Copilot CLI to build an extension that turns any codebase into a unique, roguelike dungeon. The post Dungeons & Desktops: Building a procedurally generated roguelike with GitHub Copilot CLI appeared first on The GitHub Blog.
I got nerd-sniped into the GitHub Copilot CLI Challenge and made a questionable decision: I turned my codebase into a roguelike dungeon. It started with a simple prompt: Build a GitHub CLI extension in Go that takes the current repository and turns it into a playable roguelike dungeon, with dungeons generated with BSP [snip]. And then /yolo . The result is GitHub Dungeons, a terminal game that generates a dungeon from your codebase. Rooms, corridors, and enemies, all built from your repo and rendered right in your terminal. You navigate with arrow keys, fight bugs, and hunt for the exit. Every repository produces a different map. Every commit reshapes the layout. And if your HP hits zero, you start over. <img data-recalc-dims="1" loading="lazy" decoding="async" height="432" width="1024" src="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.00-PM.png?resize=1024%2C432" alt="Screenshot of 'gh dungeons'" class="wp-image-95698" style="width:755px;height:auto" srcset="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.00-PM.png?w=1351 1351w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.00-PM.png?w=300 300w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.00-PM.png?w=768 768w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.00-PM.png?w=1024 1024w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /> 💡 Fun fact: /yolo (“you only live once”) is a Copilot CLI command (an alias for /allow-all). Fitting, since roguelikes are built around permadeath. You really do only get one life. Roguelikes trace back to games like Rogue in the 1980s – terminal-based adventures where each run generated a new dungeon, and death meant starting over. That combination of procedural generation, permadeath, and text-based interfaces (later formalized in things like the “Berlin Interpretation”) makes the genre feel surprisingly modern, and a perfect fit for the command line. GitHub Dungeons leans into that tradition. It’s written in Go, which I don’t normally use, but working with Copilot meant I could focus on behavior instead of syntax. What is procedural generation? Procedural generation (or “procgen” as the cool kids call it) is a way of creating content algorithmically instead of designing it by hand. In games, that usually means levels, maps, enemies, or items are generated at runtime using a set of rules plus a bit of randomness. So instead of designing one dungeon, you design a system that generates many. That’s what gives roguelikes their replayability: Every run is different Layouts change every time Something Something In GitHub Dungeons, that system is tied to your repo. The layout is seeded by your latest commit, so the same code produces the same dungeon, and every change reshapes it. So how does a repository actually become a dungeon? At a high level, GitHub Dungeon layouts are generated using Binary Space Partitioning (BSP), seeded by your repository’s latest commit SHA (more on BSP in a bit). That means the same codebase produces a consistent layout, while still evolving as the code changes. In practice: The same commit always generates the same map Different repositories produce layouts that feel structurally distinct As the code changes, the dungeon evolves with it It’s procedural generation—but tied directly to your codebase. That’s the idea. The interesting part was actually building it. Building it with Copilot CLI Working with GitHub Copilot CLI meant describing behavior instead of writing everything from scratch. One command that made a big difference was /delegate. Instead of just generating code inline, /delegate hands the task off to GitHub’s Copilot coding agent running in the cloud. I could describe what I wanted in plain English, kick it off, and then go do something else while it worked independently. When it finished, it opened a pull request with the results. For example,/delegate Make each level progressively harder e.g. on level 2 there are extra baddies, but more health potions Copilot generated a solid first pass asynchronously, and I reviewed and tweaked the PR from there until the balance felt right. I took the same approach to other features like adding cheat codes that make the player invincible (because why not). I even had Copilot generate a “dungeon scribe” agent, a small helper that added documentation and ASCII art diagrams to explain how dungeons were generated, which felt very on-brand for a terminal roguelike. I even had Copilot generate a dungeon scribe agent to create documentation and explain how dungeons were generated with ASCII art diagrams, which felt very on-brand for a terminal roguelike. Using Copilot (especially with /delegate) is like having an army of NPCs available to do whatever I want them to do. Lee Reilly, Dungeon Master Working this way (describing features, delegating them to Copilot, and reviewing the resulting pull requests) meant I could spend less time on edge cases and boilerplate, and more time on the player experience, including adding easter eggs for players to discover. Iterating with Copilot let me stay in a game design mindset instead of constantly switching into implementation details. Because Copilot was handling most of the build and scaffolding, I could stay in the flow of designing mechanics, testing ideas, and figuring out what actually made the game fun. Procedurally generated levels (with BSP) At the heart of each dungeon design is a technique called Binary Space Partitioning (BSP), which is a great thing to casually mention alongside middle-out compression if you want to impress your friends and colleagues. It sounds intimidating, but the idea is surprisingly simple: keep splitting a space into smaller chunks until you have a bunch of rooms you can connect. Why BSP works so well for roguelikes Roguelikes need maps that feel: Structured (not completely random nonsense) Replayable (different every run) Navigable (no dead ends or impossible layouts) BSP hits a sweet spot. It gives you: Clean, rectangular rooms Guaranteed connectivity Just enough randomness to feel organic Here’s how it works… 1. Start with a big empty space Everything begins as one big rectangle: your entire dungeon. <img data-recalc-dims="1" loading="lazy" decoding="async" height="431" width="1024" src="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.09-PM.png?resize=1024%2C431" alt="Screenshot of 'entire map' and 'start with one rectangle'." class="wp-image-95699" srcset="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.09-PM.png?w=1353 1353w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.09-PM.png?w=300 300w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.09-PM.png?w=768 768w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.09-PM.png?w=1024 1024w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /> 2. Split it (recursively) We split the space into two regions. <img data-recalc-dims="1" loading="lazy" decoding="async" height="434" width="1024" src="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.33-PM.png?resize=1024%2C434" alt="Screenshot showing two boxes: left and right." class="wp-image-95700" srcset="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.33-PM.png?w=1353 1353w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.33-PM.png?w=300 300w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.33-PM.png?w=768 768w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.33-PM.png?w=1024 1024w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /> Then split those again. <img data-recalc-dims="1" loading="lazy" decoding="async" height="433" width="1024" src="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.44-PM.png?resize=1024%2C433" alt="Screenshot showing three boxes: A, B, and C." class="wp-image-95701" srcset="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.44-PM.png?w=1353 1353w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.44-PM.png?w=300 300w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.44-PM.png?w=768 768w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.44-PM.png?w=1024 1024w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /> And again. Each split can be horizontal or vertical. 3. Stop when it gets too small We keep splitting until regions are too small to fit a room. That creates a bunch of “leaf” regions, the final building blocks. <img data-recalc-dims="1" loading="lazy" decoding="async" height="433" width="1024" src="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.54-PM.png?resize=1024%2C433" alt="Screenshot showing six boxes: A, B, C, D, E, and F." class="wp-image-95702" srcset="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.54-PM.png?w=1349 1349w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.54-PM.png?w=300 300w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.54-PM.png?w=768 768w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.53.54-PM.png?w=1024 1024w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /> 4. Turn each region into a room Each leaf becomes a room, but not perfectly aligned. We randomize size and position slightly. <img data-recalc-dims="1" loading="lazy" decoding="async" height="434" width="1024" src="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.03-PM.png?resize=1024%2C434" alt="Screenshot showing six rooms." class="wp-image-95703" srcset="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.03-PM.png?w=1353 1353w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.03-PM.png?w=300 300w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.03-PM.png?w=768 768w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.03-PM.png?w=1024 1024w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /> That slight randomness is what stops everything feeling too grid-like. 5. Connect rooms with corridors Now we connect rooms by walking back up the tree and linking siblings. <img data-recalc-dims="1" loading="lazy" decoding="async" height="435" width="1024" src="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.12-PM.png?resize=1024%2C435" alt="Screenshot showing rooms 1 and 2 separated." class="wp-image-95704" srcset="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.12-PM.png?w=1352 1352w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.12-PM.png?w=300 300w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.12-PM.png?w=768 768w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.12-PM.png?w=1024 1024w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /> <img data-recalc-dims="1" loading="lazy" decoding="async" height="433" width="1024" src="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.22-PM.png?resize=1024%2C433" alt="Screenshot showing rooms 1 and 2 connected." class="wp-image-95705" srcset="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.22-PM.png?w=1351 1351w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.22-PM.png?w=300 300w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.22-PM.png?w=768 768w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.22-PM.png?w=1024 1024w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /> Each connection is an L-shape: 6. End result: structured chaos Put it all together and you get something like this: <img data-recalc-dims="1" loading="lazy" decoding="async" height="433" width="1024" src="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.28-PM.png?resize=1024%2C433" alt="Screenshot showing the final room layout." class="wp-image-95706" srcset="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.28-PM.png?w=1353 1353w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.28-PM.png?w=300 300w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.28-PM.png?w=768 768w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-01-at-3.54.28-PM.png?w=1024 1024w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /> Rooms feel intentional Corridors make everything reachable Every run is different (but reproducible with a seed) Why this lands so well What I like about BSP is that it feels designed, even though it isn’t. It avoids the two big problems of procedural generation: pure randomness (messy), and rigid grids (predictable, boring). Instead, you get something in between… and sometimes beautiful. How to install and play it If you want to see what your own codebase looks like as a dungeon, and you already have GitHub Copilot CLI installed, you can run: gh extension install leereilly/gh-dungeons <clipboard-copy aria-label="Copy" class="code-copy-btn" data-copy-feedback="Copied!" value="gh extension install leereilly/gh-dungeons" tabindex="0" role="button"> <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path> </clipboard-copy> After that, run gh dungeons to transform your repository into a custom dungeon, ready to be conquered. Control your hero with WASD, arrow keys, or Vim keys. Your goal is to find the hidden door and escape from (and attack!) enemies over five levels. I’ve added fun features like fog of war that limit visibility, auto-attack, ability to track stats like kills and conquered levels, and more that you’ll have to discover yourself. Danger zone! If you’re feeling reckless, play it on crazy mode: you can set up a pre-commit hook that deletes your saved changes unless you beat the entire game. ⚠️ WARNING: Do not do this unless you fully understand what this will do to your repository, you’ll lose saved work and probably some sanity as well. # Create the pre-commit hook cat > .git/hooks/pre-commit << 'EOF' #!/bin/bash gh dungeons if [ $? -ne 0 ]; then echo "You died! Your changes have been stashed into oblivion..." git stash && git stash drop stash@{0} exit 1 fi EOF # Make it executable chmod +x .git/hooks/pre-commit # To be clear, you’ll lose all your uncommited changes if you enable this # and fail to beat the dungeon, adventurer. <clipboard-copy aria-label="Copy" class="code-copy-btn" data-copy-feedback="Copied!" value="# Create the pre-commit hook cat > .git/hooks/pre-commit << 'EOF' #!/bin/bash gh dungeons if [ $? -ne 0 ]; then echo "You died! Your changes have been stashed into oblivion..." git stash && git stash drop stash@{0} exit 1 fi EOF # Make it executable chmod +x .git/hooks/pre-commit # To be clear, you’ll lose all your uncommited changes if you enable this # and fail to beat the dungeon, adventurer." tabindex="0" role="button"> <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path> </clipboard-copy> (Editor’s note: Please, please, please do not do this. We are not responsible for any lost work. But Lee definitely is.) Take this with you This started as a throwaway experiment, but it changed how I think about GitHub Copilot CLI. I was able to MVP it quickly, iterate on the parts that mattered, and let Copilot handle the heavy lifting, things like BSP generation and even monsters and movement defined in a slightly cursed YAML file of Yendor. The post Dungeons & Desktops: Building a procedurally generated roguelike with GitHub Copilot CLI appeared first on The GitHub Blog.
GitHub for Beginners: Getting started with OSS contributions
Learn how to find opportunities to contribute to the open source community. The post GitHub for Beginners: Getting started with OSS contributions appeared first on The GitHub Blog.
Welcome back to GitHub for Beginners. So far, we’ve discussed GitHub Issues and Projects, GitHub Actions, security, GitHub Pages, and Markdown. This time we’re going to talk about open source software and how to contribute to that community. By the end of this post, you’ll know what open source is, how to find projects to work on, how to read an open source repository, as well as start making your first contributions. So let’s get started! As always, if you prefer to watch the video or want to reference it, we have all of our GitHub for Beginners episodes available on YouTube. What is open source? Open source software (OSS) refers to software that features freely available source code. In contrast with “closed source software,” OSS is publicly available for anyone to use and build upon. This means that all of the work, including the codebase and communication between users, is available for everyone to see. If you’re just getting started in the world of software development, browsing and contributing to open source projects is a great way to dip your toes into large, impactful projects used by countless users worldwide. GitHub is the home for open source software, so let’s look at how to find projects you can contribute to. How to find OSS projects to work on Contributing to an open source software project for the first time can be daunting—we’ve all been there! The first step is to look for projects in a language that you know which are accepting new contributors. One of the ways you can do this is to ask GitHub Copilot Chat for help. Navigate to github.com and select the Copilot icon to open a chat window. In the bottom-left corner of the chat window, use the combo box to select Ask. Enter a prompt like the following, but remember to update it for a language you’re comfortable with. I’m looking for a list of open source projects written in TypeScript that are accepting new contributors. Search GitHub and narrow down the list to repositories that use the good first issue label and have over 100 stars on GitHub. <a href="https://github.com/copilot?prompt=I%E2%80%99m%20looking%20for%20a%20list%20of%20open%20source%20projects%20written%20in%20TypeScript%20that%20are%20accepting%20new%20contributors.%20Search%20GitHub%20and%20narrow%20down%20the%20list%20to%20repositories%20that%20use%20the%20good%20first%20issue%20label%20and%20have%20over%20100%20stars%20on%20GitHub.&utm_source=github-blog&utm_medium=blog&utm_campaign=organic-blog-copilot-button" class="code-copilot-btn" aria-label="Open in Copilot" target="_blank" rel="noopener noreferrer"> <path d="M7.998 15.035c-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.201-.508-.254-1.084-.254-1.656 0-.87.128-1.769.693-2.484.579-.733 1.494-1.124 2.724-1.261 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095v1.872c0 .766-3.351 3.795-8.002 3.795Zm0-1.485c2.28 0 4.584-1.11 5.002-1.433V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-1.146 0-2.059-.327-2.71-.991A3.222 3.222 0 0 1 8 6.303a3.24 3.24 0 0 1-.544.743c-.65.664-1.563.991-2.71.991-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433ZM6.762 2.83c-.193-.206-.637-.413-1.682-.297-1.019.113-1.479.404-1.713.7-.247.312-.369.789-.369 1.554 0 .793.129 1.171.308 1.371.162.181.519.379 1.442.379.853 0 1.339-.235 1.638-.54.315-.322.527-.827.617-1.553.117-.935-.037-1.395-.241-1.614Zm4.155-.297c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Z"></path><path d="M6.25 9.037a.75.75 0 0 1 .75.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 .75-.75Zm4.25.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 1.5 0Z"></path> <clipboard-copy aria-label="Copy" class="code-copy-btn" data-copy-feedback="Copied!" value="I’m looking for a list of open source projects written in TypeScript that are accepting new contributors. Search GitHub and narrow down the list to repositories that use the good first issue label and have over 100 stars on GitHub." tabindex="0" role="button"> <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path> </clipboard-copy> Copilot will do some searching and return a list of projects you can explore filtered by the good first issue label. This label indicates that an issue is beginner friendly, and a great starting point for new contributors. This label is a great way to find issues in a project you can work on. For example, let’s say that you wanted to contribute to the vscode repository. Navigate to the vscode repository. At the top of the repository, select the Issues tab. On the Issues page, click the Labels box to open the drop down menu. In the text box on the drop down menu, start typing “good” until you see the option for good first issue. Select the good first issue label. The window will update and display a list of good first issues for you to work on. But before jumping in, you should read the contributor’s guide in the project’s repository. Most well-maintained open source projects will have one. Understanding an open source project As we just alluded to, most open source projects have a few things in common if they’re well maintained. These are the following items: A well-documented README with installation instructions. A contributor’s guide that explains how to contribute. An open source license, so everyone knows the project is free to use. At least 100 GitHub stars to show it’s used in the community. Active development so that you know a maintainer of the source code will be able to review your contributions. A good first issue label to indicate its open to new contributors. When you’re looking for a project to contribute to, these are the things you should be looking for in a repository. 💡 For more documentation on finding a good open source project, go to gh.io/gfb-oss to learn more about finding good first issues. Making an OSS contribution Now let’s look at an actual project and work on how you would submit your first issue. For this demo, take a look at the gitfolio repository. Using the bullet points above, we want to see if this would be a good project to work on. The project does have a well-documented README file. The project has a contributor’s guide: CONTRIBUTING.md. You can see the open source license: LICENSE. It has several thousands of stars, so well over our 100 benchmark. At the top of the file list, you can see the most recent check in which should be fairly recent. While writing this, the last check in was yesterday, indicating the project is being actively maintained. Based on these points, as long as you are familiar with TypeScript, this is a good repository to contribute to. However, you don’t need to be familiar with TypeScript to continue following along in the demo. Now you want to create a fork of the repository. A fork is a copy of the repository that we can freely experiment on and make changes in without affecting the original project. We usually use forks for open source contributions. If you need a refresher on forking a repository, check out this previous GitHub for Beginners blog. Navigate to the home page of the project if you are not already there. At the top of the project, click the Fork button. In the new window, leave yourself as the owner and make sure the “Repository name” is the same as the original repository (i.e., “gitfolio”). At the bottom of the window, select Create fork. In your forked copy of the repository, click README.md in the list of files. Change the file by adding some text. In the top-right, select Commit changes… Make sure to select the option at the bottom for Create a new branch from this commit and start a pull request. Select Propose changes. On the following window, click the Create pull request button. This will let you create a pull request to the main repository from your branch with the changes. At the top of the “Open a pull request” window, select compare across forks. This will show your fork’s changes compared to the original repository. If you were submitting an actual change to the repository—not just walking through a demo—this is where you would give your pull request a title and a description. You’d also want to provide a link to the issue that you were solving in the description of the pull request. At this point, you’d be ready to submit your pull request by clicking the button at the bottom of the window. However, once you do that, it no longer becomes just a change in your fork and will be a requested update on the original repository. That’s why it isn’t included in the steps above. When you do submit your pull request, it will be available and ready for a maintainer to review and, hopefully, approve! Once approved and merged, GitHub automatically applies the changes from your fork into the main branch of the original repository, the official source of truth for the codebase. What’s next? Congratulations! You’ve learned how to make your own contributions to open source software. I hope it inspires you to contribute to your favorite projects. And if you’re looking for more information, we have lots of documentation that can help. Here are a few links to get you stated: Finding ways to contribute to open source on GitHub Contributing to open source projects Contributing to a project through forking Happy coding! The post GitHub for Beginners: Getting started with OSS contributions appeared first on The GitHub Blog.
Why age assurance laws matter for developers
Youth safety requirements are moving down the tech stack to operating systems and app stores—raising new questions for open source developers. The post Why age assurance laws matter for developers appeared first on The GitHub Blog.
Policymakers around the world are advancing age assurance proposals to protect children and teens online. Some approaches restrict minors’ access to certain services or content, while others would require devices, operating systems, or app stores to collect age information and pass age signals to apps and websites. These proposals are driven by serious concerns, but without appropriate scoping, they risk imposing burdensome requirements on open source software and developer infrastructure services that do not present the same risks to minors as consumer-facing platforms. In this blog post, we’ll provide an overview of what developers should know and how to engage. The harms these laws aim to address are serious and deserve attention. Grooming for sexual purposes, exposure to violent content, and online bullying are just some of the risks young people are facing online. At the same time, participation in online communities, including open source software development, can be an important part of a young person’s education and social life. When trying to strike a balance between freedom and protection, policymakers are not always aware of how their proposals could affect developers or how the open source ecosystem operates. “Age assurance” refers to a range of approaches used to determine or estimate a user’s age. It is sometimes used interchangeably with “age verification,” which typically refers to higher-confidence methods like photo ID matching or checks against financial or identity systems. Age assurance also includes self-attestation (where users report their age) and age estimation (where age is inferred from signals, facial scanning, or behavior). These approaches span a wide spectrum, with ongoing debate about tradeoffs between accuracy, privacy, security, interoperability, and accessibility. Proposals also vary in what age thresholds trigger restrictions, the services or content covered, how parental consent should factor in, and how access is limited. While we do not discuss each approach in detail here, we encourage readers to engage with the legislation, consider different technical and policy perspectives, and think about how to protect young people online while preserving access to the knowledge, learning opportunities, and creative potential the internet enables—including opportunities to learn to code and participate in the global open source ecosystem. A poorly designed age assurance law could have significant unintended impacts for open source projects. For example, requirements that operating systems centrally collect and manage user data, or that restrict users from installing software outside of centralized app stores, would conflict with the decentralized, user-controlled norms of the open source ecosystem. Another potential pitfall is placing age assurance requirements on “publishers” of operating systems, regardless of whether they are individuals or companies. Open source operating systems are frequently iterated on, reused, and redistributed by individual contributors and small communities, many of which have limited resources and small user bases. The diversity of the software ecosystem is worth preserving. GitHub has engaged with governments on age‑related online safety proposals for several years. In some cases, including Australia’s Social Media Minimum Age legislation, we worked with policymakers to explain why open source code collaboration platforms should not be in scope. Similar exemptions appear elsewhere. France’s current Social Media Minimum Age proposal, for example, includes the same exclusions for open source code collaboration sites and online encyclopedias that appear in the EU Copyright Directive. Many policymakers recognize that access to the open source software development ecosystem delivers significant public benefits, including education, innovation, and security, and that the risks young people face from participating in open source development communities are materially different by comparison. At the same time, a growing number of laws are seeking to advance child safety goals at varying levels of the tech stack, including through operating systems and application distribution layers. This has raised new questions for developers about how these requirements apply in practice, and whether open source operating systems and developer infrastructure like GitHub could be impacted. Legislation to know California AB 1043 Digital Age Assurance Act and 2026 amending bill AB 1856: Requires operating system providers (in coordination with covered app stores) to collect self‑declared age at account setup and transmit an age‑range signal to applications via a real‑time API. Colorado SB 26-051 Age Attestation on Computing Devices: Requires operating systems and covered app stores to generate and share an age‑bracket signal with applications via a real‑time interface, with evolving definitions of “covered application” and “covered application store” shaping scope. Illinois HB 4140 Digital Age Assurance Act: Applies to operating system providers and requires collection of age data and transmission of an age‑category signal to developers via a real‑time API, closely mirroring California’s model. New York S 8102/A 8893 Device‑Level Age Assurance: Applies broadly to device manufacturers, operating systems, and app stores, requiring “commercially reasonable” age assurance (not just self‑reporting) at device activation and transmission of a verified age signal to apps and websites. This is just a selection of operating system and app store age assurance legislation in the United States. There have also been related but distinct laws focused on app stores passed in Texas (SB 2420), Louisiana (HB 570), and Utah (SB 142). These proposals are actively evolving. In Colorado, SB 26‑051 recently had a committee hearing on April 23, 2026, as part of ongoing legislative consideration. The hearing reflected the complexity of balancing child safety, privacy, and feasibility, and included strong engagement from open source developers and organizations. Committee members also signaled that the intent is not to bring open source operating systems or developer infrastructure into scope, and the latest amended text clarified that software installed outside of app stores, including software downloaded from public repositories, is not in scope. In Brazil, the Digital Statute for Children and Adolescents (Digital ECA), enforceable as of March 2026, applies broadly to digital services “likely to be accessed by children and adolescents” including operating systems, app stores, and platforms, and excludes essential internet functionalities such as open technical protocols and standards. Although the Brazilian National Data Protection Agency (ANPD) has not yet formally clarified whether or how the law applies to free and open source software, its regulatory agenda has initially prioritized “app stores and proprietary operating systems,” and recent draft guidance under public consultation indicates that systems based on collaborative models and free software should not be subject to the same obligations as proprietary services. Despite this, legal uncertainty has already driven some open source projects to restrict access in Brazil, reflecting concerns about the feasibility of compliance for non-commercial, volunteer-driven ecosystems. While the law was primarily designed for commercial actors, key questions about scope remain unresolved, making it critical for open source developers to actively participate in the ongoing public consultation to ensure implementation reflects decentralized development models and avoids unintended restrictions on access and innovation. What is an app store, really? While much of the open source community’s concern has focused on the risk that these proposals could present to open source operating systems, an equally important open question is how “application store” and “application” are defined. As drafted, some definitions of “application store” are broad enough to capture developer infrastructure—such as code collaboration platforms, package managers, and open source indexing services—simply because they allow users to access or download software. Making software available for download is not the same as operating the kind of centralized, consumer-facing marketplace that most people would understand to be an app store. It is also important to define “application” precisely. Downloading software components like source code, libraries, frameworks, models, and utilities is fundamentally different from offering a standalone executable application through a consumer app marketplace. These components are upstream building blocks, not end‑user products, and the services that host or index them do not control consumer distribution or presentation in the way traditional app stores do. Recent amendments and discussions across jurisdictions suggest regulators intend to focus on consumer‑facing distribution and services that control end‑user access. Clear statutory distinctions are needed to ensure laws align with that intent. This reflects a familiar challenge in technology policymaking. Frameworks aimed at youth safety and age assurance are typically responding to risks associated with consumer-facing services that collect and monetize user data, distribute content at scale, and rely on engagement-driven systems to shape user behavior. By contrast, platforms that support collaborative software development serve a fundamentally different function—they are built to help users create, share, and maintain code, not to attract mass audiences, amplify content, or drive passive or excessive consumption—resulting in a materially lower risk profile. Open source communities operating on services like GitHub are organized around shared technical goals and guided by norms of collaboration, reuse, and transparency, further underscoring why these developer-focused services should be distinguished from consumer-facing platforms in regulatory design. Open source software is also a key driver of economic development and innovation and functions as critical digital infrastructure. Ensuring that policies accurately reflect how open source is built and maintained is essential to preserving these benefits. When policymakers engage directly with open source developers and civil society, they are often able to refine definitions, clarify scope, and better align laws with technical realities. Uncertainty around compliance requirements can be challenging for open source developers, many of whom contribute on a voluntary basis. At the same time, there are positive examples of policymakers engaging with the open source community to strike a balanced approach. The EU Cyber Resilience Act, for example, was refined through an iterative process to get the balance right for open source. Across U.S. states, these bills continue to evolve and policymakers have shown a willingness to engage with the open source community and consider changes to align with regulatory intent and technical feasibility. An opportunity for engagement The window for constructive engagement remains open—and developer voices can make a meaningful difference. Whether through contacting elected representatives in states considering these proposals like California, Colorado, Illinois, and New York, contributing to Brazil’s Digital ECA public consultation, or engaging with organizations like the Open Source Initiative, or through foundations that steward projects that may be impacted like the FreeBSD Foundation and Debian, there are concrete ways for developers to share their perspectives—helping ensure these policies both support children’s digital safety and reflect technical realities, align with regulatory intent, and avoid unintended harm to the open source ecosystem. GitHub will continue working with policymakers and the open source community to support balanced approaches that protect young people while preserving open development. We encourage developers to stay informed, connect with open source policy organizations, and reach out to us with questions or concerns. We’ll also continue this conversation with a Maintainer Month livestream on May 22 with panelists from the FreeBSD Foundation and the Open Source Initiative to discuss the broader issues raised by these proposals and how technology policy can be designed with open source in mind. The post Why age assurance laws matter for developers appeared first on The GitHub Blog.
How researchers are using GitHub Innovation Graph data to reveal the “digital complexity” of nations
Researchers share in an interview how they used GitHub data to predict GDP, inequality, and emissions in ways that traditional economic data misses, along with our Q4 2025 data release. The post How researchers are using GitHub Innovation Graph data to reveal the “digital complexity” of nations appeared first on The GitHub Blog.
One of our goals for the GitHub Innovation Graph was to facilitate research on the economic impact of open source software and developer collaboration. In a paper recently published by Research Policy, four researchers used Innovation Graph data to do just that. I’m happy to share an interview with these researchers, along with our Q4 2025 data release. The Research Policy paper examines whether the geography of open-source software production on GitHub can reveal the “digital complexity” of nations, and whether that complexity predicts GDP, inequality, and emissions in ways that traditional economic data misses. Meet the four researchers: Sándor Juhász is a research fellow at the Corvinus University of Budapest. His work focuses on economic geography, knowledge networks, and how spatial structures shape innovation. Johannes Wachs is an Associate Professor at Corvinus University of Budapest, Director of the Center for Collective Learning at the Corvinus Institute of Advanced Study, and a researcher at the Complexity Science Hub in Vienna. His work sits at the intersection of computational social science and economic geography, with a particular focus on open-source software communities. Jermain Kaminski is an Assistant Professor at the School of Business and Economics at Maastricht University. His research specializes in entrepreneurship, strategy, and causal machine learning, with a focus on how data-driven methods can improve decision-making and innovation. He is a cofounder of the Causal Data Science Meeting. César A. Hidalgo is a professor at the Toulouse School of Economics and Corvinus University of Budapest, and he is the Director of the Center for Collective Learning. He is also the creator of the Observatory of Economic Complexity and cofounder of DataWheel. Research Q&A Kevin: Thanks so much for chatting, everyone! Could you give a quick high-level summary of the paper for our readers here? Sándor: For the last fifteen years or so, economists have been measuring the complexity of national economies by looking at what physical products countries export, what patents they file, and what research they publish. These measures turn out to be remarkably good at predicting which countries will grow, which have high inequality, amongst many other macroeconomic features. But they all have a massive blind spot: software. Jermain: Code doesn’t go through customs. It crosses borders through “git push”, cloud services, and package managers. So all that productive knowledge was essentially invisible, what some colleagues have called the “digital dark matter” of the economy. We decided to fix that using the GitHub Innovation Graph, which tracks how many developers in each economy push code in each programming language, based on IP addresses. We applied the Economic Complexity Index (ECI) to this data. The bottom line is that software ECI surfaces new information that trade flows, patents, and research data partly leave on the table. In particular, software ECI helps explain variation in GDP per capita and income inequality even after you control for all the traditional measures. Johannes: We also found that countries don’t jump randomly between software specializations. They diversify into technology stacks that are related to what they already do, just like countries in the physical economy tend to move into products similar to what they already export. This is considered the “principle of relatedness,” and it holds for software too. Kevin: Interesting! Could you provide an overview of the methods you used in your analysis? Johannes: Sure. As mentioned, the core data comes from the GitHub Innovation Graph, which gives us quarterly counts of developers pushing code by economy and programming language for 163 economies and 150 languages from 2020 to 2023. But individual programming languages aren’t really the right unit, most real software uses bundles of languages together. A web app might combine HTML, CSS, and JavaScript; a data science project uses Python and Jupyter Notebook; systems programming pairs C with Assembly. Sándor: So we built a separate dataset by querying the GitHub GraphQL API for all repositories active in 2024 to find which languages co-occur within the same repos. We computed cosine similarity between languages based on weighted co-occurrence, with a normalization scheme so that polyglot repos with twenty languages don’t dominate the signal, and then applied hierarchical clustering to group the 150 languages into 59 “software bundles.” Each bundle represents a coherent technology stack. Jermain: …and from there, it’s the “standard” economic complexity pipeline. We build a country-by-bundle matrix, compute revealed comparative advantage, essentially asking, “does this country have a disproportionate share of developers in this bundle relative to the global average?”, binarize it, and then apply the iterative method to compute the Economic Complexity Index. Countries that specialize in many non-ubiquitous bundles score high, and countries that only specialize in things everyone does score low. For the relatedness analysis, we define proximity between bundles using co-specialization patterns. If countries that are good at bundle A also tend to be good at bundle B, those bundles are close in the software space. Then we test whether countries are more likely to enter bundles that are close to their existing specializations. Kevin: Nice! Follow-up question: could you provide an “explain it like I’m five” overview of the methods you used in your analysis? César: Think of countries like kitchens. Some kitchens can cook anything, since they have an abundance of ingredients and tools, from the rarest spices to the best knives. Others are more limited. Maybe they can boil rice and do a few other simple things. Since we cannot look at the kitchens directly, we need to infer their “complexity” based on the dishes they are able to produce. This is what the economic complexity index or ECI allows you to estimate. We can infer what’s going on in the kitchen by seeing if it is a chicken and rice operation, or a place that can produce sophisticated edible foams and souffles. Originally, these methods were applied to trade data, where the dishes coming out of the kitchen were a country’s exports, but in this paper, we applied that to software. A chicken-and-rice country is a Python and JavaScript country. A Michelin-star country is one that can program certified embedded systems for aerospace and defense. Top 20 economies by software economic complexity Ranking Economy Software ECI 1 Germany 1.739 2 Australia 1.730 3 Canada 1.729 4 Netherlands 1.727 5 France 1.702 6 United States 1.695 7 Poland 1.691 8 United Kingdom 1.687 9 Italy 1.672 10 Sweden 1.620 11 Switzerland 1.620 12 Hong Kong SAR 1.595 13 Norway 1.571 14 Japan 1.552 15 Spain 1.552 16 Russia 1.530 17 Singapore 1.468 18 Taiwan 1.464 19 Belgium 1.448 20 Finland 1.444 Kevin: Thanks, that’s super helpful. I’d be curious about the limitations of your paper and data that you wished you had for further work. What would the ideal datasets look like for you? Johannes: One major drawback is that we only see public GitHub activity. That means we’re missing proprietary software entirely. Hence, we can’t see closed-source enterprise work, which is huge. So our measure likely underestimates software complexity in countries with a weaker open source software culture. Sándor: The time window is another constraint. Four years of data (2020–2023) is enough for cross-sectional analysis but too short to credibly test long-run growth predictions, which is what economic complexity measures are really designed for. Economic structures shift over decades, not quarters. We’d love to have twenty years of this data. Jermain: The dream dataset would combine GitHub-like activity data with information about the projects themselves, not just languages, but frameworks, libraries, and what the software actually does. Considering this dimension would be a natural next step for our project, and it would shed more light into software bundles and use cases. If we knew that a repo was building a fintech application versus a game engine, we could define much finer-grained capability bundles. GitHub Topics gives us a taste of this, and we used it as a robustness check, but it’s still noisy and incomplete. Kevin: Do you have any predictions for the future? Recommendations for policymakers? Recommendations for developers? César: Software is an interesting target for industrial policy because it is an industry that depends primarily on highly movable human capital (software developers). In principle, it provides an opportunity for development that can be incentivized via talent attraction programs. In practice, however, the high mobility of software talent can be a double-edged sword, since that makes it sensitive to consumer protection regulations that make it hard to work with data or worker protection schemes that distribute the risk of innovation to small and medium size firms (e.g. laws that on paper protect workers, but that in reality pass on that responsibility to the firms). The countries that figure out how to attract software talent without suffocating it with well-intentioned but poorly designed regulation will pull ahead. Johannes: For developers, understanding that places are highly specialized in the kind of software they produce is useful when they are looking to relocate. Developers can use the product space representation of software capabilities to know which countries their skillsets are a good match for. Jermain: Looking ahead, the big question is what generative AI does to this picture. If AI coding assistants lower the barrier to working in new programming languages, does relatedness weaken? Do countries diversify faster? Or does it reinforce existing advantages because the countries with the best AI infrastructure benefit most? We’re working on this, and Johannes and his colleagues have a new paper in Science on tracking the global diffusion of AI-assisted coding on GitHub. I think the answer will reshape how we think about digital complexity within the next five years. One further consideration would be how classifications of software or software bundles would be represented as NAICS or NACE industry codes. Sándor: I’d add a prediction: I think we’ll see economic complexity indices based on software data become a standard part of the policymaker’s toolkit within the decade, sitting right alongside the trade-based measures. The data is open, it updates quarterly, and it captures something that traditional data genuinely can’t. Personal Q&A Kevin: I’d like to change gears a bit to chat more about your personal stories. Johannes, I understand that you have a background in computational social science and network science, which is a bit different from the traditional economics path. Tell us more about your path to research. Johannes: I actually started in mathematics and then moved into computational social science during my PhD at Central European University in Budapest. I became enchanted by the opportunities that digital data traces present for studying human behavior. I like using network methods because they help us move between the micro level activity and interactions found in such traces and the macro outcomes. I stumbled into open source research in particular when I realized that GitHub data was this incredibly rich, publicly available record of valuable knowledge production that few people were using to study social science questions. Kevin: Sándor, I see you have a background in economic geography, which is a more traditional route compared to computational social science. What was your path toward working with software data? Sandor: I received my PhD in economic geography at Utrecht University, in a research community that was already using economic complexity to study regional development. So I was trained in thinking about places—cities, regions, industries—through the lens of networks and capability accumulation. Kevin: Jermain, it looks like you developed practical technical expertise through some entrepreneurial projects in parallel with academic training. Jermain: During my PhD at RWTH Aachen, I was a visiting researcher with Cèsar at MIT. In that time, I was also working with a colleague on a project called Moviegalaxies.com (open data) and later worked on analyzing text, speech and video data in Kickstarter projects. It was my first multimodal machine learning pipeline. From my network analysis projects, I somehow ended up analyzing passing networks for a larger German soccer team. These days my research is mostly concerned with causality and causal machine learning. In this capacity, I co-founded the Causal Data Science meeting with my colleague Paul Hünermund. Kevin: César, do I have right that you have a background in Physics? César: I started in physics, with a PhD at Notre Dame focused on complex networks. During that time, I realized that network tools could be used to describe the evolution and fate of economies. Eventually, this became a field that we know today as economic complexity, which studies the process of economic development by using tools from physics, economics, and computer science. Kevin: Finding a niche that you’re passionate about is such a joy, and I’m curious about how you’ve found living in that niche. What’s the day-to-day like for you? Johannes: Honestly, in research, the day-to-day is a mix of writing code, writing papers, and talking to people, then iterating. Of course, working at a university usually comes with teaching and administration, too. I like that I have a good amount of freedom in what I choose to work on. If a project or direction doesn’t spark joy, I can usually shift my focus. That is a unique thing. Sándor: I’d add that one of the best parts of this niche is the interdisciplinary community. On any given week I might talk to an economic geographer, a computer scientist, and a physicist about the same research question. That’s unusual and very stimulating. Kevin: Have things changed since generative AI tooling came along? Have you found generative AI tools to be helpful? Johannes: Absolutely. We use LLM tools regularly now for things like debugging data pipelines, drafting boilerplate code, and even sanity-checking statistical approaches. It’s particularly useful in a project like where you have a lot of different methods and need to coordinate work in a team. That said, LLMs are much more helpful if you already have a clear idea in mind. Kevin: Do you have any advice for folks who are starting out in software engineering or research? What tips might you give to a younger version of yourself, say, from 10 years ago? César: The key is to invest in things that grow or compound. This is easier said than done because there are always distractions and temptations. I’ve seen many scholars spend months or years working on projects just because they don’t want to lose the work that they’ve already put into them. The cost of doing that is working on other projects that might matter more in ten or twenty years. Building tools that can generate an audience, like The Observatory of Economic Complexity, Data USA, or Pantheon, was challenging, but they have borne fruit for a long time. The same is true about working on a few important papers or completing a book. The question you need to ask when working on a project is whether you honestly believe that the project will be more important in a decade from now than today. If the answer is yes, that’s probably a good project. Ten years ago, I would have told myself to trust that test more and to walk away from “almost done” projects faster. Sunk costs are the most expensive thing in a research career. Johannes: In can rather make suggestions for young researchers. The first is to build a broad question and research agenda to motivate what you do. You have to have a problem you care about so much that even partial or highly specific results about that problem get you excited. Once you have that, in practice I think there is a lot of value in generating your own data. I prefer applying a straightforward method to a bespoke dataset than applying a highly complex method to a dataset everyone knows. Jermain: My advice echoes César’s: don’t ride a dead horse. In the years after the PhD and into assistant professorship, it’s tempting to keep milking old topics while pivoting to new ones, but this leaves you straddling two worlds and mastering neither. Pick your focus deliberately, narrow enough to build real expertise, broad enough to stay curious, and be willing to let go of past work that no longer aligns, even if it feels wasteful. Sándor: I’d tell my younger self to collaborate more and earlier. This paper has four authors across five institutions in four countries. That wouldn’t have happened if any of us had stayed in our silos. Go to conferences outside your field, say yes to coffee meetings with people whose work seems tangentially related, and don’t be afraid to cold-email researchers whose work you admire. Kevin: Are there any learning resources you might recommend to someone interested in learning more about this space? César: The Observatory of Economic Complexity, for a web experience, and The Infinite Alphabet: and The Laws of Knowledge, for a book that puts this in context. Jermain: If you’re a developer curious about the economics angle, I’d honestly just recommend browsing the Observatory of Economic Complexity and looking up your own country. See what it exports, where it sits in the product space, and then think about how software fits in. It’s a very intuitive way to build the intuition before diving into the math. Kevin: Thank you, Sándor, Johannes, Jermain, and César! It’s been fascinating to learn about your current work and broader career trajectories. We truly appreciate you taking the time to speak with us and will absolutely keep following your work. The post How researchers are using GitHub Innovation Graph data to reveal the “digital complexity” of nations appeared first on The GitHub Blog.
Improving token efficiency in GitHub Agentic Workflows
Agentic workflows that run on every pull request can quietly accumulate large API bills. Here's how we instrumented our own production workflows, found the inefficiencies, and built agents to fix them. The post Improving token efficiency in GitHub Agentic Workflows appeared first on The GitHub Blog.
GitHub Agentic Workflows is like a team of street sweepers that clean up little messes in your repo. These teams significantly improve repo hygiene and quality, but as with all agentic work, cost is a growing concern for developers. And because CI jobs like agentic workflows are automatically scheduled and triggered, costs can accumulate out of view. Thankfully, making automations more efficient is easier than doing the same for interactive desktop sessions. Work done during a developer session can be hard to predict, but agentic workflows’ work is fully specified in YAML and repeats every execution. Because we maintain and use GitHub Agentic Workflows in our own GitHub repositories, we worry about token efficiency as much as our users. That is why in April 2026, we began to systematically optimize the token usage of many of the workflows that we rely on every day. This post describes what we instrumented, the optimizations we applied, and our preliminary results. Logging token usage We rely on hundreds of agentic workflows in our repos for maintenance and CI. All workflows run as GitHub Actions against real API rate limits. We are building the plane as we fly it and burning jet fuel as we go. Before we could optimize our token consumption, we needed to know how tokens were consumed. The first challenge we faced was that each agent framework (Claude CLI, Copilot CLI, Codex CLI) emitted logs in a different format, and usage data could be incomplete for historical runs. Thankfully, the agentic-workflows security architecture uses an API proxy to prevent agents from directly accessing authentication credentials. This proxy gave us a way to capture token usage across all runs in a single normalized format, regardless of agent framework. Every workflow now outputs a token-usage.jsonl artifact with one record per API call that contains input tokens, output tokens, cache-read tokens, cache-write tokens, model, provider, and timestamps. Combining this data with the rest of the workflow’s logs gave a historical view of how tokens were typically spent and allowed us to optimize for future runs. Workflows optimizing workflows With token data in hand, we built two daily optimization workflows. A Daily Token Usage Auditor reads token usage artifacts from recent workflow runs, aggregates consumption by workflow, and posts a structured report. Its job is to flag any workflow that has significantly increased its recent usage, surface the most expensive workflows, and take note of anomalous runs (e.g., a workflow that normally completes in four LLM turns taking 18). When an Auditor flags a workflow, a Daily Token Optimizer looks at the workflow’s source and recent logs to create a GitHub Issue describing concrete inefficiencies and proposing specific optimization. The Optimizer has found many inefficiencies that we would have otherwise missed. Of course, the Auditor and Optimizer are agentic workflows themselves, and their token usages also appear in daily reports to create a small virtuous cycle. Eliminating unused MCP tools Based on our initial Auditor and Optimizer results, the most common inefficiency is unused MCP tool registrations. Because LLM APIs are stateless, agent runtimes typically include the MCP tool function names and JSON schemas with each request. In practice, this means the full set of tools can become part of every call’s context. For a GitHub MCP server with 40 tools, this can add 10–15 KB of schema per turn. If the agent only uses two tools, the remaining 38 are pure overhead added to every request. Workflow authors naturally start with a full tool-set since it is the path of least resistance, and the agent can figure out which tools it needs. But as time goes on, most workflows rely on a narrow, stable set of tools. The Optimizer identifies this pattern by cross-referencing tool manifests against actual tool calls and recommends pruning unused tools from the configuration. In our smoke-test workflows, removing unused tools from the MCP configuration reduced per-call context size by 8–12 KB, saving several thousand tokens per run with no change in behavior. Replacing GitHub MCP with GitHub CLI Removing unused MCP tools is a relatively simple win. A larger structural opportunity was replacing GitHub MCP calls for data-fetching operations like retrieving pull request diffs, file contents, and review comments with calls to the GitHub CLI. This change did more than reduce the overhead of unused tools because an MCP tool call is a reasoning step in addition to data retrieval. The agent must decide to call the tool, formulate its arguments, and receive its output as part of the context. That’s a full round-trip LLM API call, consuming tokens for the tool-use JSON schema, the argument block, and the response. Calling gh pr diff, by contrast, is a deterministic HTTP request to GitHub’s REST API with no LLM involvement. We used two strategies for this migration: Pre-agentic data downloads. For data that an agent will always need like a pull request diff or the list of changed files, we added setup steps in the workflow that run gh commands before the agent starts and writes the results to workspace files. The agent reads those files instead of making MCP calls. This eliminates tool-call overhead and allows the agent to take advantage of its extensive training in bash scripting to efficiently process the data. In-agent CLI proxy substitution. Pre-downloading isn’t possible in cases where the agent determines what to fetch at runtime. In these cases we rely on a lightweight transparent HTTP proxy that routes CLI traffic to GitHub’s API servers without exposing an authentication token to the agent. The agent runs gh pr view –json and gets structured data back, just as a user would from a terminal. This reduces token usage without compromising our zero-secrets security requirement for the agent. Together, these techniques move the majority of GitHub data-fetching out of the LLM reasoning loop. Measuring efficiency gains is not easy Once we began to optimize our workflows, we ran into a more nuanced problem: how do you know whether a change made things more efficient, or just made the workflow do less (and perhaps worse) work? There are three confounding factors. Not all tokens are created equal. Running the same workflow on Claude Haiku versus Claude Sonnet produces similar token counts but cost very differently. Haiku costs roughly 4× less per token than Sonnet, so a workflow that switches models appears unchanged in raw token count but represents a significant cost reduction. To account for this, we use an Effective Tokens (ET) metric that applies model multipliers to each token type: ET = m × (1.0 × I + 0.1 × C + 4.0 × O) <clipboard-copy aria-label="Copy" class="code-copy-btn" data-copy-feedback="Copied!" value="ET = m × (1.0 × I + 0.1 × C + 4.0 × O)" tabindex="0" role="button"> <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path> </clipboard-copy> where m is a model cost multiplier (Haiku = 0.25×, Sonnet = 1.0×, Opus = 5.0×), I is newly-processed input tokens, C is cache-read tokens, and O is output tokens. Output tokens carry 4× weight because they are the most expensive token type across all major providers. Cache-read tokens carry only 0.1× weight because they are served from cache at a fraction of the cost of fresh input. This formula normalizes consumption across model tiers so that a 10% ET reduction means a genuine 10% cost reduction regardless of which model is in use. The workload is a live repository. As far as we know, there is no agentic-workflow benchmark that we can use to optimize our token usage. When we began looking at token usage by our workflows, we found that in one run a workflow would handle a five-line fix, and in the next run it would handle a 200-line pull request. The first run naturally uses fewer tokens, but the difference is not due to a sudden change in efficiency. Raw token counts can confuse workload variation with fluctuations in efficiency. We try to normalize this by tracking LLM API call counts alongside token counts; constant LLM turns-per-run and falling tokens-per-call indicate genuine efficiency improvement. Both falling together may indicate that less work is being done. Does quality change? Understanding output quality is the hardest consideration. A lighter model running a more constrained workflow might produce lower-quality output. We looked at the process-level signals like output tokens per LLM call, turn counts per run, and tool-call completion rates to approximate quality. For our optimized Smoke Copilot workflow, all three remained stable across the optimization period even as token consumption fell. The workflow completes in roughly five LLM turns every run, before and after the optimizations. Of course, these are process signals, not outcome signals. We cannot directly observe whether the quality improved, degraded, or was stable, because there is no ground-truth “correctness.” Measuring tokens-per-unit-of-correct-work requires additional instrumentation and thought. Initial results After deploying the auditor and optimizer across a dozen production workflows in the gh-aw and gh-aw-firewall repos, we downloaded token-usage artifacts for runs before and after each was optimized and computed ET for each run. Nine of the 12 workflows received optimizer-recommended changes. We include results only for workflows with at least eight runs in both the pre- and post-optimization periods. These are: Auto-Triage Issues, Daily Compiler Quality, Community Attribution, Security Guard, and Smoke Claude. <img data-recalc-dims="1" loading="lazy" decoding="async" height="504" width="1024" src="https://github.blog/wp-content/uploads/2026/05/graph.png?resize=1024%2C504" alt="Graph showing token savings across Auto-Triage Issues, Daily Compiler Quality, Community Attribution, Security Guard, adn Smoke Claude." class="wp-image-95794" srcset="https://github.blog/wp-content/uploads/2026/05/graph.png?w=1486 1486w, https://github.blog/wp-content/uploads/2026/05/graph.png?w=300 300w, https://github.blog/wp-content/uploads/2026/05/graph.png?w=768 768w, https://github.blog/wp-content/uploads/2026/05/graph.png?w=1024 1024w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /> Auto-Triage Issues shows a clear, sustained reduction of 62% across 109 post-fix runs. Daily Compiler Quality shows 19% improvement over 12 post-fix runs, and Daily Community Attribution shows 37% improvement over eight post-fix runs. In the gh-aw-firewall repo, Security Guard, which audits every pull request for security-sensitive changes, and Smoke Claude an integration test that exercises the firewall’s Claude CLI path, had the most post-fix runs and show improvements of 43% and 59%, respectively. Run frequency matters as much as per-run savings. Auto-Triage Issues fires on every new issue (averaging 6.8 runs per day with a max of 15) while Daily Compiler Quality runs at most once per day. 62% savings and 6.8 runs/day compounds quickly: over the observation period, Auto-Triage’s optimization saved roughly 7.8 M ET in aggregate, assuming the pre-optimization rate. Security Guard and Smoke Claude run even more frequently. When prioritizing which workflows to optimize, run frequency is as important as per-run consumption. It is important to note that not every optimization that the agent recommends translates into measurable ET savings, especially over short observation windows on a live repository where workload varies day to day. For example, the Contribution Check workflow experienced a 5% increase in ET, and we will discuss it in greater detail below. Take aways Based on these results, we highlight three patterns. Many agent turns are deterministic data-gathering. Auto-Triage Issues shows the strongest sustained improvement in gh-aw (−62% across 109 post-fix runs) because the optimization eliminated structural inefficiency: many agent turns were spent on reads that required no inference, such as fetching issue metadata and scanning labels. Moving those reads into pre-agentic CLI steps before the agent starts removed them from the LLM reasoning loop entirely. The same pattern drove Security Guard’s −43% reduction in gh-aw-firewall: a relevance gate now skips the LLM entirely for pull requests that don’t touch security-sensitive files. The cheapest LLM call is the one you don’t make. Contribution Check illustrates a confounding factor: 82–83% of input tokens were cache reads (data-gathering), but average ET increased 5%. This is due to a workload shift rather than optimization failure: in the pre-optimization period 41% of runs processed small pull requests (ET < 100K) and 39% processed large pull requests (ET > 300K). The post-optimization period coincided with a burst of development activity, and the workflow processed 9% small pull requests and 65% large pull requests. Output tokens, which carry a 4× weight in the ET formula, rose 14% as the agent reviewed bigger diffs. The optimization likely improved per-turn efficiency, but the shift toward heavier workloads masks that gain in the aggregate numbers. Unused tools are expensive to carry. Among the excluded gh-aw workflows, the Glossary Maintainer is an instructive case. A single tool—search_repositories—was called 342 times in one run, accounting for 58% of all tool calls, despite being completely unnecessary for a workflow that only scans local file changes. Removing it from the toolset was the optimizer’s recommendation. In gh-aw-firewall, Smoke Claude’s −59% reduction was driven in part by aggressive MCP tool pruning combined with a model-tier switch to Haiku. The Daily Community Attribution workflow illustrates the limits of this approach: it was configured with eight GitHub MCP tools and made zero calls to any of them across an entire run, but removing them did not reduce ET. Tool manifests were a small fraction of this workflow’s overall context. A single misconfigured rule can cause runaway loops. Also among the excluded workflows, Daily Syntax Error Quality was the highest-ET workflow in the project before optimization. The root cause was a one-line misconfiguration: the workflow copied test files to /tmp/ then called gh aw compile*, but the sandbox’s bash allowlist only permitted relative-path glob patterns. Every compile attempt was blocked. Unable to use the tool it needed, the agent fell into a 64-turn fallback loop in which it manually read source code to reconstruct what the compiler would have told it. One fix to the allowed bash patterns eliminated the loop. We did not have enough baseline runs to precisely quantify the improvement, but the pathology was clear and the fix was unambiguous. What’s next? The tools we use to optimize our workflows including API-level observability, automated auditing workflows, MCP tool pruning, and CLI substitution are all available today in the GitHub Agentic Workflows framework. Another upcoming optimization is refactoring monolithic agents into teams of subagents using smaller and cheaper models. The next step is to move from workflow-level optimization to system-level optimization. A workflow run is not really one flat sequence of API calls. It is a chain of episodes: short phases of work like gathering context, reading artifacts, retrying after a failure, or synthesizing a final answer. Once you can see those episodes clearly, you can ask much better questions. Which episode actually caused a costly run? Which episodes are mostly repeated work, blocked work, or failed work? Which ones should stop being agentic entirely and become deterministic pre-steps? That same logic applies at the portfolio level. Repositories do not run one workflow in isolation. They run a fleet of agentic automations that often trigger on the same events, inspect the same diffs and logs, and produce adjacent judgments. That means cost is not just a property of a single workflow, but also of overlap across the portfolio. The next analyses we want are portfolio-level ones: where workflows are duplicating reads, where several workflows should be consolidated, and where shared intermediate artifacts should be cached instead of rediscovered by each run. Those open questions are genuinely hard. Measuring goodput still requires outcome instrumentation that does not yet exist at scale for agentic CI workflows, and understanding episode and portfolio efficiency requires richer lineage data than most systems collect today. But that is the direction that matters. The proxy-level observability and optimizer workflows have already changed how we develop and deploy new agentic automations. We add token monitoring from day one rather than retrofitting it later, and increasingly we think in terms of avoidable work across the whole automation fleet, not just expensive runs in isolation. If you’re running agentic workflows in CI and wondering whether you’re spending more than you need to, the first step is the same as ours: add the API proxy, turn on logging, and let the data tell you where to look. If you want to add the workflows mentioned here, you can simply drop them into your repo using the gh-aw CLI: gh extensions install github/gh-aw gh aw add githubnext/agentic-ops/copilot-token-audit githubnext/agentic-ops/copilot-token-optimizer <clipboard-copy aria-label="Copy" class="code-copy-btn" data-copy-feedback="Copied!" value="gh extensions install github/gh-aw gh aw add githubnext/agentic-ops/copilot-token-audit githubnext/agentic-ops/copilot-token-optimizer" tabindex="0" role="button"> <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path> </clipboard-copy> Running them alongside your existing CI will give you immediate visibility into usage and help continuously optimize your workflows over time. We’d love to hear how others are approaching this problem. Share your thoughts in the community discussion or join the #agentic-workflows channel of the GitHub Next Discord. Explore the GitHub Agentic Workflows repo > Editor’s note: This post was updated on May 13, 2026, to clarify some reduction rates numbers. The post Improving token efficiency in GitHub Agentic Workflows appeared first on The GitHub Blog.
Agent pull requests are everywhere. Here’s how to review them.
A practical guide to reviewing agent-generated pull requests: what to look for, where issues hide, and how to catch technical debt before it ships. The post Agent pull requests are everywhere. Here’s how to review them. appeared first on The GitHub Blog.
You’ve probably already approved one without realizing it. The tests passed. The code was clean. You merged it. But it was agent-generated—and that ease of approval is exactly the problem. A January 2026 study, “More Code, Less Reuse”, found that agent-generated code introduces more redundancy and more technical debt per change than human-written code. The surface looks clean. The debt is quiet. And reviewers, according to the same research, actually feel better about approving it. This isn’t an argument to slow down. It’s an argument to be intentional. There’s a difference. Agent pull requests are already saturating review bandwidth The volume is already staggering. GitHub Copilot code review has processed over 60 million reviews, growing 10x in less than a year. More than one in five code reviews on GitHub now involve an agent. That’s just the automated review pass. The pull request themselves are multiplying faster than reviewers can handle. The traditional loop—request review, wait for code owner, merge—breaks down when one developer can kick off a dozen agent sessions before lunch. Throughput has scaled exponentially. Human review capacity hasn’t. The gap is widening. You’re going to review agent pull requests. The question is whether you’ll catch what matters when you do. Who (or what) actually wrote this pull request Before you look at a single line of diff, you need a model for what you’re reviewing. A coding agent is a productive, literal, pattern-following contributor with zero context about your incident history, your team’s edge case lore, or the operational constraints that don’t live in the repository. It will produce code that looks complete. But that “looks complete” failure mode is dangerous. You’re the one who carries that context. That’s not a burden. It’s the actual job. The part of review that doesn’t get automated is judgment, and judgment requires context only you have. One note for authors If you’re opening an agent-generated pull request, edit body before you request review. Agents love verbosity. They describe what’s better explored through the code itself. Annotate the diff where context is helpful. And review it yourself before tagging others, not just to check correctness, but to signal that you’ve validated the agent captured your intent. Reviewing your own pull request isn’t optional when agents are involved. It’s basic respect for your reviewer’s time. Now, back to reviewers. The pull request lands in your queue. The author did their part. Here’s what to watch for. Red flags to watch for 1. CI gaming Agents fail CI. When they do, they have an obvious path to get tests passing: remove the tests, skip the lint step, add || true to test commands. Some agents take it. Any change that weakens CI is a blocker. Full stop. Before approving any agent pull request, check: Did coverage thresholds change? Were any tests removed, renamed, or marked as skipped? Did the workflow stop running on forks or pull requests? Are any CI steps now gated behind conditions they weren’t before? Yes, to any of those means you need an explicit justification before you continue. 2. Code reuse blindness This is the highest-ROI thing you can do as a reviewer. Agents look for prior art. They’ll find a pattern in the codebase and replicate it, often without checking whether a utility that already does the same thing exists somewhere else. The symptoms: new utility functions that duplicate existing ones with slightly different names, validation logic reimplemented in multiple places, middleware written from scratch that already lives in a shared module, helpers that are “almost the same” but with different names. The agent’s local context doesn’t include the full picture of what exists across your repository. You do. For every new helper or utility in an agent pull request, do a quick search. If you find an equivalent, don’t leave a comment. Require consolidation before merge. The cost of leaving duplicated logic is that agents will find it as prior art and replicate it further. 💡Pro tip: Require justification for adding new utilities in agent pull requests above a size threshold. This catches the duplication problem early. 3. Hallucinated correctness The obvious hallucination (calling an API that doesn’t exist, referencing a variable out of scope) gets caught in CI. The dangerous one is subtler: code that compiles, passes every test, and is wrong. Off-by-one errors in pagination. Missing permission checks on a branch that’s never hit in tests. Validation that short-circuits under an edge case the agent never considered. Wrong behavior under a race condition that only surfaces at scale. Trace it, don’t just scan it. Pick the most critical path in the diff. Follow it from input through every transform to output. Check boundary conditions (zero, max, empty), missing validation on external values, permission checks on every branch, and surprising conditional logic. Require a new test that fails on the pre-change behavior. If the agent can’t write a test that would have caught the bug it claims to fix, the fix is incomplete or the understanding is wrong. 4. Agentic ghosting You leave a thorough review. You explain the issue, provide context, suggest a direction. The pull request goes quiet. Or the agent responds and misses the point entirely and runs in circles. You invest another round. Still nothing useful. Larger pull requests with no structured plan correlate strongly with agent abandonment or misalignment. The larger and less scoped the pull request, the more likely you’re going to sink review time into something that goes nowhere. Before you invest deep review on a large agent pull request check the pull request history. Has it been responsive in previous rounds? Does it have a clear implementation plan, or did the agent just start writing code? If there’s no plan, request a breakdown before you write a single comment. Copy-paste version: “This pull request is too large for me to review without a clearer implementation plan. Can you break it into smaller scoped units, or add a summary of what each part does and why it’s structured this way? Happy to review after that.“ Firm, short, not personal. And it saves you an hour. 5. Untrusted input in workflows Prompt injection in CI agents is real and underappreciated. Here’s the pattern: an agent workflow reads content from a pull request body, an issue, or a commit message. That content gets interpolated into a prompt. The prompt goes to a model. The model output gets piped to a shell command. The whole thing runs with GITHUB_TOKEN permissions. When you’re reviewing any workflow that calls an LLM, these are blockers: Is untrusted user input, pull requestbodies, issue bodies, commit messages, being interpolated into prompts without sanitization? Is GITHUB_TOKEN write-scoped when it only needs read access? Is model output being executed as shell commands without validation? Are secrets accessible to the agent step or being printed to logs? What to require before merge: least-privilege permissions in the workflow YAML (permissions: read-all is a reasonable default), sanitize and quote untrusted content before it touches a prompt, separate the “analysis” step from the “execution” step with a human approval gate for anything touching production, never eval model output. Time Step What to do 1–2 min Scan and classify Look at the file list and diff size. Narrow task (docs, CI, small change) or complex (multi-file, logic, performance, tests)? That classification sets your review depth for everything that follows. 2–3 min Check CI changes first Before reading a single line of app code, look at anything touching .github/workflows, test configs, coverage settings, or build scripts. Flag anything that weakens CI. Stop sign check. 3–5 min Scan for new utilities Search for new functions, helpers, or modules. For each one, do a quick repo search to check for duplicates. Flag anything that reinvents existing functionality. 5–8 min Trace one critical path Pick the most important logic change. Trace it end-to-end: input → transforms → output. Check boundary conditions, permissions, unexpected branching. This is the step you can’t skip. 8–9 min Security boundaries If this PULL REQUEST touches any workflow that calls an LLM or handles untrusted input, run through the security checklist above. 9–10 min Require evidence For any non-trivial logic change, require a test that fails on the pre-change behavior. No rollback plan for risky changes? Ask for one. When to request a smaller pull request: The diff touches more than five unrelated files You can’t describe the purpose of the pull request in one sentence The agent has no implementation plan or the pull request body is empty CI is failing and the only changes in the diff are to test files Let Copilot review it first Use automated review for what it’s good at: catching the mechanical stuff before a human has to. Copilot code review flags style inconsistencies, obvious logic errors, missing error handling, and type mismatches. It handles the low-level scan. That frees you up for the judgment work, which is where your time actually matters. Treat it as a prerequisite, not a replacement. Let Copilot run first. If it catches something obvious, let the author address it before you invest your review time. You can tune this with custom instructions specific to your team: flag anything that modifies CI thresholds, surface new utilities for deduplication review, check that every external input is validated. The more specific your instructions, the more useful the automated pass. 💡 Pro tip: I recently experimented with codifying my own review checklist using the Copilot SDK. Instead of remembering to run the same security checks on every pull request, I built a workflow that takes my personal checklist—auth on admin endpoints, tests actually running, safe env variable handling—and runs it against the diff automatically. If it finds critical issues, it blocks the merge. Judgment is the bottleneck, and that’s fine The surface area of code is growing. pull request volume is growing. The time you spend scanning boilerplate should shrink. What doesn’t shrink is the context you carry. The things you know about your system that aren’t written down anywhere. That’s what makes your review valuable, and it’s the part that doesn’t get automated. Three takeaways: Any CI weakening is a hard stop. Let the agents scan first. You trace the critical path. Red flag checklist as your default on complex agent pull requests. Read the docs > The post Agent pull requests are everywhere. Here’s how to review them. appeared first on The GitHub Blog.
Validating agentic behavior when “correct” isn’t deterministic
How to build the “Trust Layer” for Github Copilot Coding Agents without brittle scripts or black-box judgements by using dominatory analysis. The post Validating agentic behavior when “correct” isn’t deterministic appeared first on The GitHub Blog.
Modern software testing is built on a fragile assumption: correct behavior is repeatable. For deterministic code, that assumption mostly holds. But for autonomous agents like Github Copilot Coding Agent (aka Agent Mode), especially as we explore the frontiers of integrated “Computer Use,” that assumption breaks down almost immediately. As agents move beyond simple code suggestions to interacting with real environments like UIs, browsers, and IDEs, correctness becomes multi-path. Loading screens can appear or disappear, timing shifts, and multiple valid action sequences can lead to the same result. Unless our GitHub Actions workflows are robust enough to account for this variability, it’s common for an agent to succeed at a task while the test still fails—a “false negative” that halts production. This blog post explores how to move past brittle, step-by-step scripts and toward an independent “Trust Layer” for agentic validation. We will demonstrate a model that focuses on essential outcomes rather than rigid paths, providing a way to validate behavior that is explainable, lightweight, and ready for real-world CI pipelines. The challenges of agent-driven validation Imagine you’re responsible for a GitHub Actions pipeline that relies on Copilot Agent Mode to validate real-world workflows. The agent could be leveraging Computer Use, navigating within a containerized cloud environment, for the workflow validation. On Tuesday, the build is green. On Wednesday, the test fails—even though no code has changed. Here’s what happened: A minor network lag on the hosted runner caused a loading screen to persist for a few extra seconds. The agent waited, adapted, and successfully completed the tasks correctly. But your CI pipeline still flagged the run as a failure—not because the task failed, but because the execution path no longer matched the recorded script or assertion timing. The agent didn’t fail. The validation did. This surfaces three recurring pain points that create a “trust gap” in agent-driven testing: False negatives: The task succeeded, but the test runner could not tolerate variation. Fragile infrastructure: Tests fail due to timing, rendering, or environmental noise unrelated to correctness. The compliance trap: The outcome may be correct, but a regression is flagged because the agent’s behavior diverges from what the automated test expected. We’re in a transition period where agentic systems like Github Copilot Coding Agent are enabling faster development, but our traditional validation approaches remain rigid. In deterministic software, correctness is as simple as matching a specific input to a known output. But with agents, the process in between is intentionally non-deterministic. As agents are increasingly deployed in production, correctness isn’t about following a prescribed set of steps—it’s about “reliably achieving the essential outcomes.” To scale these systems, we need a validation framework that can distinguish between “incidental noise” (e.g., a loading screen) and “critical failures” (e.g., failing to save data). Correctness shifts from “did this happen?” to “what had to happen for success to be real?” Why existing testing approaches break down for autonomous agents Traditional testing tools work well when execution paths are fixed. They struggle when behavior branches—the tools begin to fracture, not because they’re poorly engineered, but because they assume a stable sequence. When we apply these to a Copilot Coding Agent, including when navigating a containerized environment, the limitations become clear across four common paradigms: Assertion-based testing: Requires manual, labor-intensive specifications for every check and fails to account for valid alternative execution paths. Record-and-replay tools: Highly sensitive to environmental noise; minor rendering differences or timing variations often trigger false failures. Visual regression testing: Compares screenshots in isolation without understanding the broader execution flow or semantic meaning. ML oracles: These “black boxes” require thousands of training examples and offer no explainability when they flag a behavior as incorrect. While these approaches differ in implementation, they share a common structural assumption: Correctness is defined by adherence to a particular sequence of observable states. For agentic systems, that assumption breaks down. To build true developer trust in these systems, including Github Copilot, we must move beyond checking linear scripts and start validating structured behaviors. Reframing correctness: Essential vs. optional behavior To move past brittle tests and build the Trust Layer, we have to fundamentally change how we define “correct.” In agentic systems, correct executions don’t have to look identical. They do need to share a common logical structure. The conceptual shift Think of a computer use-enabled Github Copilot Coding Agent performing a search in VS Code in a containerized cloud environment. In one run, a loading screen appears for several seconds; in another, the UI loads instantly (shown below). <img data-recalc-dims="1" loading="lazy" decoding="async" height="582" width="1024" src="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-6.10.57-PM.png?resize=1024%2C582" alt="A computer use-enabled Github Copilot Coding Agent shown performing a search in VS Code in a containerized cloud environment." class="wp-image-95758" srcset="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-6.10.57-PM.png?w=1241 1241w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-6.10.57-PM.png?w=300 300w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-6.10.57-PM.png?w=768 768w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-6.10.57-PM.png?w=1024 1024w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /> Scenario: Opening VS Code A traditional test sees these as two different results. But to a developer, the loading screen is incidental; it doesn’t change whether the task was successful. We can classify agent behavior into three categories: Essential states: Milestones that must occur for success to be real, such as reaching the “Search Results” screen. Optional variations: Incidental states such as loading spinners or decorative UI changes that vary based on environment. Convergent paths: Different sequences of steps (like using a hotkey vs. a menu) that ultimately rejoin at the same outcome. A loading screen may appear or not. But search results must appear. Only one of these determines correctness. From intuition to theory: Dominator analysis The distinction between “must-have” and “incidental” behaviors is a concept rooted in compiler theory known as dominator relationships. In a control-flow graph, a node A “dominates” node B if every path from the start to B must go through A. By applying dominator analysis to agent execution traces, we can automatically identify: Which states are mandatory Which states are optional Where different paths converge This lets us extract a minimal, explainable definition of correctness. Modeling executions as graphs, not scripts To capture the complexity of agentic behavior, we must move away from treating executions as linear, one-dimensional scripts. Instead, our framework models behavior using a graph-based structure known as a Prefix Tree Acceptor (PTA). From linear traces to structured graphs In this model, an execution is not a series of commands but a directed graph where: Nodes represent observable states, such as screenshots for UI agents or code snapshots for development agents. Edges represent transitions, capturing the actions (clicks, keystrokes, or API calls) taken to move between states. Why graphs matter Treating executions as graphs allows us to represent branching and convergence—concepts that are impossible to capture in a linear script. Branching accounts for non-deterministic environment changes, like the presence or absence of a loading screen. Convergence identifies where these different paths rejoin, signaling that the agent has successfully navigated a variation and returned to the primary task flow. By shifting the representation from a sequence of steps to a structured behavior model, we stop penalizing agents for taking a different path and start validating whether they followed a logically sound one. How we solve it: A structural approach to correctness To move agents from experimental demos to production-grade infrastructure, our team developed a novel validation algorithm that moves away from rigid scripts and instead learns by example. To test this, we focused on a complex non-deterministic environment: an AI agent navigating Visual Studio Code via “Computer Use.” By observing just 2–10 successful sessions, our algorithm automatically constructs a “ground truth” model that distinguishes between an agent’s valid variations and actual failures. The workflow: From traces to a “master” graph Capture (PTA Construction): We collected 2–10 successful execution traces and converted them into Prefix Tree Acceptors (PTAs), directed graphs where nodes represent observable UI states and edges represent actions. Generalize (Semantic Merging): Our algorithm merged these traces into a unified graph. It employed a three-tiered equivalence detection framework—combining fast visual metrics with LLM semantic analysis—to decide if two states are logically equivalent, such as ignoring a timestamp change while flagging a missing UI control. Extract the Skeleton (Dominator Analysis): We applied dominator analysis to the merged graph to identify “essential states,” milestones every successful run must pass through—while automatically filtering out “optional” states like loading spinners. This approach is uniquely powerful for developers because it requires no manual specification and no large-scale model training. Because the resulting model is a graph of actual execution states, the decisions are entirely explainable. When validation fails, our algorithm provides clear failure reasoning by identifying exactly which essential state was missed. Deciding when two states are “the same” State equivalence is the hardest problem in agent validation. For example, how do we know if two different screenshots represent the same logical UI state? We solve this using a three-tier equivalence detection framework that moves from fast visual metrics to deep semantic understanding: Visual metrics: We use fast perceptual hashes and structural similarity (SSIM) to catch near-identical states immediately. Semantic analysis via LLM: When visual metrics are ambiguous, we use a multimodal LLM to decide if differences are semantically meaningful. For example, the LLM knows to ignore a timestamp change or a different window decoration but will flag a different error message or missing UI control. Conservative merging: We only merge states when the model is certain they are equivalent, allowing the graph to naturally branch where execution paths genuinely diverge. This is not a naive pixel-by-pixel comparison, nor is it “LLM hand-waving” where the model is asked to judge the whole task. By using the LLM defensively and sparingly to resolve specific ambiguities, our framework remains robust enough to handle UI noise but precise enough to detect a real regression. Extracting what actually matters with dominator analysis Once the various execution traces are merged into a unified graph, our algorithm applies dominator analysis to isolate the core skeleton of the task. Defining “essential” through dominance: In graph theory, State A dominates State B if every possible path from the start to B must pass through A. In our model, we define a state as essential if it is a dominator for the successful completion of the task. The filtering process: By calculating these mathematical relationships, the algorithm automatically distinguishes between “must-have” milestones and “incidental” noise. In our VS Code experiments, the “Search Dialog” state is identified as an essential milestone because it is a mathematical dominator—it is logically impossible to reach the results without first triggering the search. Conversely, a “Loading” screen dominates nothing; because it is bypassed in faster runs, the algorithm flags it as an optional variation rather than a requirement for success. This ensures the “Trust Layer” framework only alerts you when a critical step is missed—not when the environment fluctuates. <img data-recalc-dims="1" loading="lazy" decoding="async" height="586" width="1024" src="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-6.11.19-PM.png?resize=1024%2C586" alt="A computer use-enabled Github Copilot Coding Agent shown performing a search in VS Code in a containerized cloud environment. This time, the flow from State 1.1 to State 1.2 and State 1.3 is labeled 'Loading screen or intermediate blank Desktop screen (State 1.2) are optional states.' And the flow from State 2.1 to State 2.2 is labeled 'Desktop with VS Code icon being clicked or Start Menu are some example states (State 2.1) which should precede open VS Code window (State 2.2)." class="wp-image-95759" srcset="https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-6.11.19-PM.png?w=1250 1250w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-6.11.19-PM.png?w=300 300w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-6.11.19-PM.png?w=768 768w, https://github.blog/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-6.11.19-PM.png?w=1024 1024w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /> Scenario: Opening VS Code By extracting these essential nodes into a dominator subtree, we create a “ground truth” model that represents the minimal, explainable definition of correctness. This shifts the validation focus away from the specific steps the agent took and toward the critical checkpoints it was required to hit. Validating new executions in practice With the dominator tree established as our ground truth, validating a new, unseen execution becomes a process of structural comparison rather than a search for a perfect match. This ensures that as long as an Agent Mode hits the “must-have” milestones, it is free to navigate the environment, or adapt its integrated Computer Use path, as it sees fit. When a new execution trace arrives, our validation algorithm extracts its sequence of states and checks it against the dominator tree using topological subsequence matching. The logic: We don’t require the new trace to be identical to the reference; we only require that the essential states appear in the correct relative order. Handling extras: If the reference sequence is A → B → C and the agent produces A → X → B → Y → C, the test still passes because the extra states (X, Y) are treated as incidental noise. Detecting failure: A failure is triggered only if an essential state is skipped or if the states appear out of the required logical order. Scoring and explainability Our framework produces more than just a binary pass/fail; it provides a coverage metric and a clear explanation: Coverage: Calculated as the percentage of matched essential states relative to the total number of states in the reference model. Failure reasoning: If a trace fails, our algorithm identifies exactly which state was missing (e.g., “Failed: State ‘Search Results’ never reached after ‘Search Dialog’”). This level of detail transforms the validation from a “black box” into a diagnostic tool that developers can actually use to debug their agents and their environments. What we learned from evaluation To prove the efficacy of this structural approach for Trust Layer, we conducted a controlled experiment comparing our Dominator Tree method against an agent’s self-assessment (where the Computer-Use Agent, or CUA, reports its own success) in a real-world scenario: a Copilot Agent custom VS Code extension test suite. The accuracy gap In tests designed to differentiate successful executions from those failing due to product bugs or agent errors, the results were definitive: Metric CUA Self-Assessment PTA (Dominator Tree) Accuracy 82.2% 100% (+17.8) Precision 83.3% 100% (+16.7) Recall 60.0% 100% (+40.0) F1-Score 69.8% 100% (+30.2) While the agent (CUA) frequently misreported failures as successes, often due to timing out or misinterpreting its own state, the Dominator Tree achieved perfect differentiation by focusing on whether essential milestones were actually reached. Identifying “not a bug” scenarios The most significant impact for developers is in the reduction of “false alarms.” When a test fails, you need high-signal feedback to know if the product code is broken or if the agent simply stumbled due to environmental noise. The “Self-Verification” Gap: In our evaluation, the agent’s internal self-assessment (CUA) was completely unable to identify “Not a Bug” scenarios (0% F1-score). This shows that agents cannot yet reliably grade their own homework in non-deterministic environments. The Structural Advantage: By using state and action equivalence within the dominator model, our independent Trust Layer achieved a 52.2% F1-score in correctly identifying when a failure was an agent execution error rather than a product regression. The takeaway Structural validation beats self-reported success by a wide margin. By moving the “source of truth” from the agent’s internal logic to a learned external structure, we can significantly reduce the manual review time wasted on flaky test results and false positives in CI pipelines. Where this fits in developer workflows today For this Trust Layer framework to be effective, it must move beyond a research prototype and integrate directly into the systems developers use every day. By treating correctness as a learned structure rather than a rigid script, we can significantly improve the reliability of production-grade automation within the GitHub ecosystem. Integration points This approach is designed to strengthen several critical areas of the software development lifecycle: GitHub Actions Pipelines: By reducing false negatives caused by environmental noise (like transient loading screens), this method provides a “higher signal” for automated builds, preventing unnecessary pipeline blocks. Regression testing: Developers can use a handful of verified traces from a stable version to create a “ground truth” model that automatically validates future updates. Agent evaluation: Instead of relying on an agent to report its own success, teams can use structural validation to measure how often an agent actually hits essential milestones. UI automation: The framework allows for more robust automation of complex desktop and web apps where UI elements or paths may shift slightly between versions. The ultimate goal of this framework is to move agents from “experimental demos” to “production infrastructure.” By providing reasoning, where a failure clearly points to a missing essential state, we give developers the transparency they need to trust autonomous systems in their workflows. What’s next While structural validation represents a significant leap forward, our current framework has a few boundaries as it moves toward full maturity. Current limitations include: Requirement for success traces: The algorithm “learns by example,” meaning it requires 2–10 successful execution traces to build its ground truth model. It cannot yet learn or define correctness exclusively from failure logs. LLM dependency: Our semantic equivalence checking currently relies on multimodal LLM access. While this enables the “intelligence” to ignore timestamps or window decorations, it introduces an external API dependency and associated latency into the validation layer. Temporal blind spots: The current implementation validates the order of events, but cannot yet flag if a specific state (like a loading spinner) persists for too long. Future work includes: Temporal and negative constraints: Future work focuses on capturing timing requirements (e.g., “loading must resolve within five seconds”) and learning from negative examples to explicitly block known failure paths. Hierarchical and multimodal abstraction: The framework will evolve to cluster low-level screenshots into high-level concepts (e.g., a “Launch Sequence”) while integrating non-visual signals like DOM structures, accessibility trees, and network traffic. Online learning: We aim to implement real-time model refinement. As our algorithm validates new successful runs, it will recompute dominators to continuously improve its understanding of what is truly “essential.” Why this matters now As AI agents move from experimental demos to core infrastructure, validation has to evolve with them and move past brittle scripts to resilient systems. We don’t need black-box models to judge other black-box models. We need structural guarantees developers can inspect, reason about, and trust. By combining classic compiler theory (i.e., dominator analysis) with multimodal AI, we’ve demonstrated that it’s possible to learn an explainable, robust definition of success from just a handful of examples. This framework for the Trust Layer provides: Efficient learning: Automatic derivation of ground truth from passing examples. Operational robustness: Secure handling of non-deterministic behavior and environmental noise. Total transparency: Explainable results with clear reasoning that developers can act upon. As we move forward, focusing on these practical, explainable paths will be essential to ensuring that the GitHub Copilot Coding Agent is not just powerful, but also a trustworthy component of the developer workflow. This is particularly critical with the increasing adoption of Computer Use in the overall AI-native development lifecycle. By moving the “source of truth” from an agent’s internal logic to a learned external structure, we provide the guarantees needed to make autonomous agents viable, production-grade tools in modern infrastructure. Our journey toward verifiable autonomy is just beginning. For a deep dive into our Dominator Analysis-based framework, you can read the complete paper. The post Validating agentic behavior when “correct” isn’t deterministic appeared first on The GitHub Blog.
Welcome to Maintainer Month: Celebrating the people behind the code
What maintainers are telling us, what we've shipped, and how to celebrate the people behind open source. The post Welcome to Maintainer Month: Celebrating the people behind the code appeared first on The GitHub Blog.
At a Maintainer Unconference in Brussels this year, a breakout session had maintainers jotting down thoughts on the future of open source. One sticky note stood out: As AI gets better at writing code, human work around code becomes more important and more invisible. Mentoring new contributors, building trust across a community, making the judgement calls that shape a project’s direction: that’s the work that turns a repository into a living collaboration. And with the speed of AI, the people doing the work are carrying more than ever. Pull requests merged on GitHub have nearly doubled year over year, and agentic workflows are accelerating the pace even further. As one maintainer put it: How much time should I spend on something that you didn’t spend any time on? I’ve been part of Maintainer Month for five years now. The conversations I’m having with maintainers this year feel different—there’s a weariness, but there’s also innovation. Maintainers are converging on standards like agents.md, building trust systems, and designing workflows that put them back in control. In February, Ashley Wolf named the influx of low-quality contributions open source’s Eternal September. Maintainers told us exactly what they needed. We took notes. Six years ago we started Maintainer Month because the people behind open source deserve better tools, real resources, and community. This year, we’re going bigger on all three. Tools: Big releases for maintainers this month Maintainers need better ways to manage who contributes, how, and at what volume. In the Eternal September post, we shared some of the directions we were exploring. Here’s where things stand. Granular contribution limits: This one’s for every maintainer who’s watched their pull request queue turn into a firehose. This gives maintainers the ability to introduce limits on how many pull requests a new or unknown user can make in your project. No more choosing between closing the doors and opening the floodgates. You control how much you let in. Pull request archiving pairs with it. Sweep spam pull requests out of public view. No more emailing support to clean up your repo. And there’s a brand new accessibility best practices guide on opensource.guide. Practical steps to make your project usable by everyone. And we haven’t been waiting around. Since February, we’ve also shipped: Pull request creation controls: restrict pull request creation to collaborators only, or disable pull requests entirely. (Also useful for mirrors, roadmaps, or other repositories where pull requests aren’t appropriate.) Pinned comments on issues: pin the most important comment to the top of any issue thread. Sort notifications oldest-first: work through your backlog in order instead of always chasing the latest ping. File upload in issue forms: structured issue templates now support file uploads. We’re building these because maintainers asked for them. Specifically, repeatedly…and often loudly! We hear you, and we’re going to keep shipping. Please keep flagging. Resources: Who else is showing up We asked companies and foundations across the ecosystem to show up for Maintainer Month. And they did! Sentry, OpenJS Foundation, Daytona, and more partners are putting real resources behind maintainers: free tools, compute credits, threat intelligence, conference tickets, and more. Open source runs on maintainers, and we’re proud to partner with GitHub to celebrate and support them. As the ecosystem scales, maintainers are doing more than ever to keep projects secure and reliable. Maintainer Month is a chance to connect, share knowledge, and remind them they’re not doing this alone. Robin Ginn, OpenJS Foundation Partners across the ecosystem are offering real resources for maintainers. Here’s what’s available: Sentry: Sentry for Open Source Daytona: $100 in compute credits for maintainers (and up to $10,000 for projects via Startup Grid) Mockoon: Free Mockoon Cloud accounts for OSS projects Ref.tools: Free project planning tools for your team Arachne Digital: Free cyber threat intelligence reporting for OSS projects Radix / .Tech: Free 1-year .tech domain for maintainers OpenJS Foundation: 15% discount on RenderATL tickets (code: OPENJSGITHUB) Open Source Initiative: The maintaine.rs book, free for all maintainers Web Summit: Conference tickets (details coming soon) Last year, Sentry celebrated companies that fund open source on a Times Square billboard for Maintainer Month. That’s the energy we’re looking for. Want to join them? Whether you’re a company that depends on open source, a startup, or an educator—reach out about the Partner Pack or explore the GitHub Partner Program for more ways to get involved. Maintainers, here’s where you can claim your Partner Pack benefits. And if you maintain open source tools for science: the new Open Source for Science Fund just launched with $20 million in funding. Grants up to $1 million for projects supporting data-intensive research. Letters of intent open May 11. Community: You shouldn’t have to do this alone There are 20+ events and streams (and counting!) scheduled throughout Maintainer Month. Here are a few we’re excited about: FOSS United Foundation: Maintainers Meetup Delhi (May 9, India). Unconference-style gatherings for maintainers across India. PyCon US 2026 (May 13–19, Long Beach). Come find us there! Discussion: How should corporations support OSS maintainers? (May 14, virtual). An open discussion on corporate OSS support. Open Source Assistive Technology Hackathon (May 21-22, San Francisco). A two-day hackathon focused on making open source assistive technology more accessible. What Maintainers Need to Know about Open Source Licensing, SBOMs and Security (May 27, virtual). The EU’s Cyber Resilience Act is here and it affects open source. Come get the practical rundown. We’d love to see you there, whether you maintain a project with millions of users or you’re just getting started. Check out the full schedule > Part of something bigger One thing we heard over and over from maintainers this year: they want to be ”part of something bigger and not just being a solo maintainer.” If you maintain an open source project and want to connect with others who get it, request to join the Maintainer Community, a vetted space to share experiences, get support, and have honest conversations. It’s where the “how are you handling this?” sharing of best practices is happening. Community members also get access to an exclusive tier of the Partner Pack, with deeper discounts, higher credit limits, and offers you won’t find in the public pack. Request to join > Get involved Sponsor a maintainer. Financial support is one of the most direct ways to say “your work matters.” Host or attend an event. Browse the schedule or submit your own event. Share your story. Tag #MaintainerMonth on social media. Tell people about the project you maintain and what it means to you. The best way to celebrate maintainers is to make their work visible. Say thank you. Find a project you depend on and tell the maintainers you appreciate them. It matters more than you think. Open source is changing fast. What hasn’t changed is that real people wake up every day and choose to maintain the software the world runs on. They do it because they believe in it, and millions of us depend on that choice. This month is for them. Show up, pitch in, say thank you. Let’s make it count. See everything happening this Maintainer Month > The post Welcome to Maintainer Month: Celebrating the people behind the code appeared first on The GitHub Blog.