As software development has grown over the last decades, our code bases have gotten bigger and bigger.
AI — and especially SWE AI agents — will only accelerate this process. However, the way we navigate around and observe the structure of the codebase hasn't changed much. Our IDEs display a tree of files and folders for navigating our codebase, even though related logic might actually be stored in different places throughout our codebases. Copernicus explores how we can utilise LLMs to understand and navigate our codebases — beyond how they're stored on disk.
Why?
Traditionally, IDE display a file explorer as one of the core elements of their UI. The file tree is often the main way of navigating code, alongside reference finding, goto definition, and other language-level tools. However, traditional file explorers have a couple of problems and limitations:
- Finding relevant files is difficult, especially if developers don't know what they're looking for.
- The information we can encode in the file system is minimal. While we try to name our files and folders with appropriate names ("controllers" or "utils," etc.), it's difficult to convey the semantic meaning of code in a hierarchy of folders. Frameworks and languages often institute conventions to make it easier for developers to predict where to find certain logic, but developers must learn of those implicit conventions.
- With file systems, we can't go "lower" than a file; we have no way of encoding information that one part of the file is doing thing A, while another part of the same file is doing thing B.
- File trees provide a horizontal structure, but there's no way to pick vertical slices out of them. For example, I want to open all the code related to authentication in my web application. This code can spread across multiple files, and those files may not be located in the same folder, but rather in different locations throughout the repository. With a traditional file tree, there's no easy way to get all those files other than navigating through the file/folder hierarchy to multiple files.
- File trees provide a static view. I can't look at the file system from different points of view or through different "lenses." But as a developer, I'm sometimes interested in how my UI components are structured, and in other cases, I'm interested in user workflows, and so on. Each such "lens" is potentially its own tree-like hierarchical structure representing parts of the codebase.
Exploration
Project Copernicus utilises LLMs to index your codebase and generate an alternative, natural-language-based file tree using the semantic understanding of the codebase. This file tree generation is dynamic, and takes into account the "focus" and "dimension" that is of interest to the user at that particular moment.
Indexing is the process of gathering all the relevant files and sending each one to an LLM, which generates a summary for the entire file, breaks the file into smaller, semantically meaningful chunks, and summarises those chunks. Indexing is performed asynchronously in the background. When a user opens a new VS Code instance, we attempt to index all the source files in the repository. Additionally, we reindex any file that the user saves inside VS Code.
Generating the tree is handled by the process we call grouping. Grouping takes all the generated summaries from the index and uses an LLM to create semantic 3-level hierarchies based on those summaries, as well as the user's "focus" and "dimension" inputs. Grouping is performed on demand: when users open the panel for the first time, and whenever the user explicitly triggers grouping again. "Focus" allows the user to instruct the LLM to focus only on a particular subset of the codebase, such as "UI" or "backend." "Dimension" defines a way in which a hierarchy of groups and sub-groups should be created. For example, we want the hierarchy to represent user workflows or layers of the application.
Further potential exploration
Project Copernicus is a relatively small exploration, and it has been designed with a fairly limited scope. Even considering that, there are still some improvements that could have been made to make the current prototype better:
- Going deeper - currently, the leaves of our tree are files; however, we could go lower than that and use chunks (parts of the files). This would mean that users don't need to scan through long files to find relevant snippets, but instead could navigate to the exact location.
- Scalability and performance - performance of both indexing and grouping is directly related to the size of the repository. So far, we've tested it in a medium-sized repository - running it on such a repository (of ~150 files) produces ~500 chunks with summaries. Indexing itself is relatively quick (it takes ~20 seconds for this repo), and what's more important, it happens in the background, so the user does not perceive it. However, grouping performance is more critical to the final UX - we've tried to make it feel a bit faster by using response streaming, but probably more work needs to be done here.
- Graph instead of tree - when you think about the semantic structure of the codebase, we often should deal with a directed graph structure rather than a hardcoded, 3-level tree structure that Project Copernicus currently uses. It may be interesting to investigate different grouping prompts and alternative UIs for displaying such graph information. On the other hand, a considerable advantage of a limited-level tree is its familiarity to the users — it's not a new interface to learn, but instead a straightforward replacement/addition to the file tree they already know.
What's next
While Project Copernicus is just a quick prototype, we're excited to continue exploring and prototyping tools that help developers to better understand their code base.
Message us at @githubnext.com or send us an email at next@github.com