SCIP: a language-agnostic format for code indexes
SCIP Code Intelligence Protocol
At a glance
- What is it?
- SCIP is a Protobuf schema and a set of bindings for indexing source code, and the point of making it language-agnostic is that a single index format can power go to definition, find references and find implementations across ecosystems. The repository ships the schema, Go and Rust bindings, generated TypeScript and Haskell bindings, and a scip command line tool for working with the indexes.
- Who is it for?
- Adopt SCIP if you are building or consuming code intelligence and want one index format across languages, because a dozen indexers already emit it, from scip-clang to rust-analyzer and scip-typescript, and the Go and Rust bindings carry the utility functions you would otherwise write. Do not adopt it if you need a search engine rather than a symbol index, because SCIP is a schema for structured code facts and says nothing about text search.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
An index format, deliberately separate from any one language
SCIP, pronounced skip, is a language-agnostic protocol for indexing source code, which can be used to power code navigation functionality such as go to definition, find references and find implementations.
The word protocol is doing the work here. A language server indexes one language and answers questions inside that language's world. SCIP defines a format that a compiler or a parser can emit and that any consumer can read, so a Java index, a TypeScript index and a Rust index can be merged into one store and queried together. That is what makes cross-repository navigation and polyglot features possible without asking every language to implement a common server interface.
The repository is the specification plus the tooling around it. It includes a Protobuf schema for SCIP in scip.proto, rich Go and Rust bindings that include many utility functions to help build tooling on top of SCIP, auto-generated bindings for TypeScript and Haskell, and the scip CLI, which the README says makes SCIP indexes a breeze to work with.
The choice of Protobuf is the load-bearing technical decision. A schema definition in a language-neutral wire format means an indexer in any language can emit the data without depending on this repository's code, and a consumer in any language can read it. The bindings are conveniences on top of that, and the README is explicit that you can skip them and generate code for the schema using the Protobuf toolchain for your own ecosystem.
The project is Go by primary language, Apache-2.0 licensed, with the default branch on main, the site at scip-code.org, and the last push on 2026-10-15.
A dozen indexers already speak it
The README lists the tools that emit SCIP data, and the list is the best argument for the format.
scip-java covers Java, Scala and Kotlin. scip-typescript covers TypeScript and JavaScript. rust-analyzer covers Rust, which is the notable one because the Rust language server was already an indexer before SCIP existed and had to be adapted. scip-clang covers C++ and C, and scip-ruby, scip-python and scip-dotnet, the last covering C# and Visual Basic. scip-dart is a community project from Workiva, and scip-php is from a separate contributor. The odd one out is debian-lsp, which indexes Debian packaging files.
That last entry is worth a moment, because it is a good test of whether a format is genuinely language-agnostic or merely multi-language. Debian packaging metadata is not a programming language with a compiler and a type system, and an indexer for it emits SCIP all the same. If your data has symbols, definitions and references, the format does not care what produced them.
Other tools that use SCIP include the Sourcegraph CLI and the SCIP CLI in this repository, and the README points at the Sourcegraph documentation for more details about indexers.
The practical value of that list is that consuming SCIP data does not require you to run any of these indexers yourself if your ecosystem already has one. If your code is TypeScript, scip-typescript probably already emits what you need, and the work becomes merging the index into your store rather than building an indexer.
The CLI, and the three questions the README asks you
The scip CLI is the tool for working with indexes, and the README says there are binaries on the releases page and that you can compile one locally:
git clone https://github.com/scip-code/scip.git --depth=1
cd scip
go build ./cmd/scipThe shallow clone is a hint about the intent, since the repository history is not what you need to build the tool. The CLI reference is in docs/CLI.md, and --help covers the usage information.
The README then splits its audience three ways, and the split is a good map of the project.
If you are interested in better understanding the motivation behind SCIP, there is an announcement blog post and a design document. If you are interested in writing a new indexer that emits SCIP, there is documentation on how to write an indexer, plus the debugging section in the development docs. If you are interested in consuming SCIP data, you can either use one of the provided language bindings, or generate code for the SCIP Protobuf schema using the Protobuf toolchain for your language ecosystem, and again the debugging section is worth reading.
That last point, the debugging section, appears twice, once for indexer authors and once for consumers. It is there because a SCIP index is a binary artefact produced by a toolchain, and when a symbol does not resolve the usual questions, is the index wrong, is the indexer wrong, or is the consumer wrong, apply the wrong schema.
The repository also lists a Contributing section, pointing at the development document for the project structure and common workflows, and a code of conduct hosted on the project site.
Consuming the format: bindings, or generated code
There are two ways to read SCIP data, and the README presents them as a genuine choice rather than a preference.
The first is to use one of the provided language bindings, which live in the bindings/ directory of the repository. The Go and Rust bindings are described as rich and as including many utility functions to help build tooling on top of SCIP, so they are not thin wrappers around the generated Protobuf code, they are the places where the awkward parts of working with an index have already been dealt with. The TypeScript and Haskell bindings are auto-generated, so they are the plain Protobuf surface in those languages.
The second is to generate code for the SCIP Protobuf schema using the Protobuf toolchain for your language ecosystem, which means you get the wire format without depending on this repository at all. That matters for a tool that has to support languages the project has not written a binding for, and it is the reason the schema file sits at the root of the repository where a Protobuf build can find it.
The choice is between convenience and dependency. The Go and Rust bindings save work and pull in a dependency on a specific version of the bindings package. Generated code is a build step you own and a file you can review, and it pins you to the schema version rather than to the library.
The README also mentions a design document in the docs/ directory, and for anyone implementing an indexer that document is where the semantics live, because a Protobuf schema tells you the shape of the message but not the meaning of a relationship.
The Go module has a trick worth reading
The go.mod at the root of the repository is short and contains one line that explains the layout of the whole project.
The module is github.com/scip-code/scip and it declares Go 1.26.0, and then it has a replace directive:
replace github.com/scip-code/scip/bindings/go/scip => ./bindings/go/scipand a requirement on the same module at a placeholder version:
require github.com/scip-code/scip/bindings/go/scip v0.0.0-00010101000000-000000000000That version string is the Go convention for a module that is replaced by a local directory, so the Go bindings are a separate module that lives inside this repository and is wired in locally. The effect is that a change to the bindings and a change to the schema can be developed together and tested together, which is what you want when the bindings are the reference implementation of the format.
The rest of the requirements are the tooling: a CLI framework, the Protobuf runtime, a SQLite driver, a compression library, a pretty printer, a line counter and a statistics package, with testify for the tests. The presence of a SQLite driver and a compression library is a hint about the CLI, since a code index is large and has to be stored and moved around efficiently.
There is also a go.work file and a go.work.sum, so the repository is set up for Go workspace mode, which lets the bindings module and the root module be built together without publishing anything.
The repository layout and the build tooling
The top-level listing shows a project that is a specification, a set of bindings and a tool, and it is organised accordingly.
scip.proto is the schema and it is at the root, which is where a Protobuf build expects to find it. bindings/ holds the generated and hand-written bindings for each language. cmd/ holds the command line tool. docs/ holds the design document, the CLI reference and the development guide, and reprolang/ is a small reference language used for testing, which is the standard way to check that an indexer and a consumer agree without needing a real compiler in the loop.
The build tooling is Nix based. There is a flake.nix, a flake.lock and a checks.nix, so the development environment and the checks are defined in one place and pinned, which matters for a repository whose releases are used by tools in many different language ecosystems.
The Protobuf generation is configured with buf.yaml and buf.gen.yaml, so the code generation for the bindings is driven by Buf rather than by a hand-written script.
On the formatting side there is a .prettierrc and a .prettierignore, which is an unusual choice in a Go project and suggests the non-Go files in the repository, the Protobuf schema and the documentation, are formatted by the same tool.
The licence is Apache-2.0, and the release history is regular: v0.8.1 on 2026-06-04, v0.9.0 on 2026-06-29 and v0.10.0 on 2026-09-03, with the last push on 2026-10-15.
Editorial conclusion
Adopt SCIP if you are building or consuming code intelligence and want one index format across languages, because a dozen indexers already emit it, from scip-clang to rust-analyzer and scip-typescript, and the Go and Rust bindings carry the utility functions you would otherwise write. Do not adopt it if you need a search engine rather than a symbol index, because SCIP is a schema for structured code facts and says nothing about text search. Before you commit, pin the schema version rather than the tool version, since the Protobuf definition is the contract that every indexer has to match, and decide whether you want the bindings, the CLI, or generated code for your own ecosystem, because the README offers all three and they come with different maintenance obligations.
Frequently asked questions
What is SCIP and what is it for?
A language-agnostic protocol for indexing source code, used to power code navigation such as go to definition, find references and find implementations. The repository holds the Protobuf schema, Go and Rust bindings with utility functions, auto-generated TypeScript and Haskell bindings, and the scip command line tool for working with indexes.
Which languages already have SCIP indexers?
scip-java for Java, Scala and Kotlin, scip-typescript for TypeScript and JavaScript, rust-analyzer for Rust, scip-clang for C++ and C, scip-ruby, scip-python, scip-dotnet for C# and Visual Basic, scip-dart, scip-php, and debian-lsp for Debian packaging files.
How do I read SCIP data in a language without a binding?
Generate code for the SCIP Protobuf schema using the Protobuf toolchain for your ecosystem, as the README describes. The schema file scip.proto is at the root of the repository so a Protobuf build can find it, and the repository also ships a debugging section in the development docs for when a symbol does not resolve.
How do I build the scip CLI?
Binaries are published on the releases page, and you can build one locally with a shallow clone of the repository, a change into the directory and go build ./cmd/scip. The CLI reference is in docs/CLI.md, and the project also provides a flake.nix with checks.nix for a pinned development environment.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/scip-code-scip)Was this useful?