On this page
The longest function in any open-source repo with 10,000+ GitHub stars that we index is RunPanoramaStitchSelfTest in Microsoft PowerToys: 6,967 lines in an 18,048-line C++ file, and it is a test suite written as one function. It is the longest of 53 repos at that star count with a function-length record in our index.
We record the longest function in every repo we index. For this study we took the popular ones, opened each function in the source at the exact commit we indexed, measured it again by hand, and read it to find out why it got that long. Almost none of them are the textbook "long method".
The longest functions in popular repos
The ten longest functions in repos with 10,000+ stars run from 2,223 to 6,967 lines. The table lists them longest first, then three more from further down the list that explain something. Lengths are at the commit we indexed (linked); the last column is the function on the default branch on 6 October 2026.
| Repo | Function | Lines | What it is | Today |
|---|---|---|---|---|
| microsoft/PowerToys | RunPanoramaStitchSelfTest | 6,967 | a self-test suite | 6,967 |
| NousResearch/hermes-agent | run_conversation | 6,591 | the agent loop | 48, split up |
| vectorize-io/hindsight | _register_routes | 5,209 | 99 HTTP routes | 5,260 |
| openclaw/openclaw | runEmbeddedAttempt | 4,972 | one agent run | 35, split up |
| pewdiepie-archdaemon/odysseus | setup_email_routes | 4,640 | 57 email routes | |
| andrewyng/openworker | make_integration_tools | 4,505 | 133 tool functions | |
| tt-a1i/archify | compileWorkflowInternal | 3,565 | a compiler pass | |
| debpalash/voicestudio | DubPage | 2,775 | a single TSX page component | |
| colbymchenry/codegraph | main | 2,348 | 22 CLI commands | |
| emdash-cms/emdash | createMcpServer | 2,223 | 55 MCP tools | |
| Further down | ||||
| apache/airflow | get_provider_info | 1,703 | generated | |
| go-gitea/gitea | registerWebRoutes | 1,464 | the web route table | 1,470 |
| fastapi/fastapi | FastAPI.__init__ | 988 | 39 documented parameters | 988 |
Scroll the table sideways to see every column.
A blank "Today" cell means we did not re-measure it on the current branch.
Reading down the "What it is" column, the functions sort into four kinds: registries, generated code, a test that grew, and core loops. Only the core loop is the kind of long function people usually warn about.
Why do functions get this long?
1. The registry
Half the list is one shape: a single function that defines everything a server or CLI exposes. Hindsight's _register_routes declares 99 HTTP routes inside one function. Odysseus' setup_email_routes declares 57. emdash's createMcpServer registers 55 MCP tools. codegraph's main sets up 22 CLI commands. openworker's make_integration_tools defines 133 inner functions, one per tool. Gitea's registerWebRoutes is close to 800 route calls in a row.
Each handler needs the same shared objects (the app, the database client, the config). The easiest way to give them all access is to define every handler inside one function that receives those objects, so each handler is a closure over them. The language calls that one function, so every length metric counts it as one, even though it reads like a module with a long table of contents.
A registry is less of a problem than its length suggests, because every entry looks the same and the function scans easily. It starts to hurt at merge time: when several people add routes in the same week, they all edit the same 5,000-line function and the conflicts land in one place. Splitting routes by area (one register function per resource) fixes that without changing behavior.
2. Generated code
Generated functions are long by construction and should be measured, then excluded. Airflow's get_provider_info is 1,703 lines, and its file opens with "NOTE! THIS FILE IS AUTOMATICALLY GENERATED AND WILL BE OVERWRITTEN!" It returns one large dictionary describing the Google provider, and nobody edits it by hand.
Suricata, the network security monitor, has a 3,500-line C function in a file marked "DO NOT EDIT. THIS FILE IS AUTO-GENERATED." It has 6,655 stars, so it is not in the table, but it makes the same point. If a tool flags generated code, the fix belongs in the tool's configuration.
3. The test that grew
The longest function on the list is a test, and it grew the way tests do: one scenario per bug. PowerToys' RunPanoramaStitchSelfTest belongs to ZoomIt's panorama capture, which stitches screenshots into one long image as you scroll. The function runs scenario after scenario: small scroll steps, near-duplicate frames, and dark code editors whose repeating line pattern can fool the matcher into locking onto 2x or 4x the real scroll distance. Several scenarios are labelled as regression tests for specific bugs, with the debug log name that reproduced them.
That is a reasonable way for a test to grow. Each scenario is self-contained, and one function means shared setup, a fixed order and one exit code. It still runs to 6,967 lines, and most test frameworks would let you register each scenario as its own test and get per-scenario failures for free. It is the same function on the default branch today.
4. The core loop
This is the long function people mean when they warn about the pattern, and it is where the most interesting things happened. Hermes Agent's run_conversation was 6,591 lines at our index of 19 August: the whole agent loop for one user turn, with retries, compression, streaming, tool calls and cancellation, in one function with 521 if/elif lines. About 28% of its lines were comments, many of them long explanations of a past bug and why the code handles it the way it does. openclaw's runEmbeddedAttempt was 4,972 lines at our index of 26 June, with 90 awaits in one body.
Both have since been split. On today's default branches, run_conversation is 48 lines and runEmbeddedAttempt is 35, with the work moved into smaller functions around them. Both repos are among the fastest-moving on GitHub, with hundreds of commits a day, and our guess is that the pace is why: a single function that every change has to touch becomes a bottleneck for the whole team.
FastAPI's __init__ is mostly documentation
FastAPI's __init__ is 988 lines, and about 830 of them are the parameter list. It takes 39 parameters, and each one carries its own documentation inline through Annotated[..., Doc("...")], so editors can show the docs on hover. The body that does the work is around 160 lines, so counting it as a long function mostly counts documentation.
What to do about long functions in your own code
Decide which of the four kinds you have before you refactor.
- A registry is easy to read and painful to merge: split it by area when merges start to hurt.
- Generated code should be excluded from your metrics.
- A test that grew can become one test per scenario, mostly for better failure reports.
- A core loop is the one to split first, before every feature has to go through it.
repowise records the longest function for every repo it indexes, along with the file it lives in, and links that file's health findings. To rank what to split first across a whole repo, run repowise health --refactoring-targets for the stored queue of refactoring plans, or read the refactoring priorities guide and the best refactoring tools roundup. The code health feature page explains how files are scored.
To see your own repo, paste any GitHub URL and open the stats page. Here is PowerToys.
How we measured
For every public repo with 500+ stars that has a stats record in our index (106 repos, with FastAPI counted once although we list it under two owners), we took the longest function the parser found. We kept repos with 10,000+ stars, downloaded each file from GitHub at the exact commit we indexed, and measured the function again: Python with the standard ast module; C, C++, Go, JavaScript and TypeScript by matching braces from the definition. Every number in the table matched our index.
Length is lines from the definition to the closing line, including comments and blank lines. "Today" means the default branch on 6 October 2026. Counts of routes, tools, if lines and comments are simple line matches, so treat them as approximate. To reproduce a row, open the linked commit and count the line range in the URL.
FAQ
- What is the longest function in an open-source project?
- Among repos with 10,000+ stars in our index, it is PowerToys'
RunPanoramaStitchSelfTestat 6,967 lines, a self-test for ZoomIt's panorama capture. Hermes Agent'srun_conversationwas nearly as long (6,591 lines) before it was split into small functions. - How long should a function be?
- There is no universal limit, and studies disagree on a number. A practical rule is that a function should hold one idea you can keep in your head, and a function you must scroll through to understand deserves a look. Registries and generated code are the exceptions that read fine at length.
- Are long functions always bad?
- No. A route or tool registry is repetitive and easy to scan, and generated code is never edited by hand. Long functions hurt most when they hold branching logic that every change must touch, such as an agent loop with hundreds of conditionals.
- How do I find the longest functions in my codebase?
- Run a function-length or complexity report from your linter, or run
repowise health --refactoring-targetsto get a ranked queue of what to split. repowise also shows the longest function for any indexed repo on its stats page. - Why were Hermes Agent's and openclaw's giant functions split?
- We did not find a statement from either project. Both are among the fastest-moving repos on GitHub, and a single function that every change touches becomes a merge bottleneck, which is our reading of why both were split.



