What a SCIP moniker is, and how to get one
The stable symbol name every semantic query takes as its argument.
Written By Dustin
Last updated About 3 hours ago
Most tovio semantic queries take a moniker — find-def, find-refs, callers, tested-by and types all require one, and impact accepts one. (search takes free text instead, and diff takes commit addresses, not symbols.) It is worth two minutes to understand what a moniker is, because guessing at the syntax is the usual reason a query comes back empty.
It is a name, not an address
A moniker is a SCIP-style descriptor: a qualified name string that identifies a symbol logically. It is not a hash of the code, which is precisely the property that makes it useful — edit a function's body and the moniker is unchanged, so TOVIO can follow the same symbol across commits and across files.
The trailing punctuation carries meaning, and is part of the name:
So greet() is not a moniker and greet(). is. A missing trailing dot is the single most common reason find-def prints nothing.
Do not hand-write them — search
tovio semantic search greetSearch takes free text, not a moniker, and prints the exact monikers back to you with the file and line where each is defined and how many references each has. Copy one and feed it to the query you actually wanted:
tovio semantic find-refs 'greet().'Quote the moniker in your shell. # starts a comment in most shells and will otherwise truncate the argument silently.
Matching is exact
The moniker is the join key, compared by string equality — there is no global ID allocation pass and no fuzzy matching at lookup time. A moniker either matches or it does not. Fuzzy matching happens in search, and only there.
Some symbols deliberately have none
A file-local symbol — a private helper, a closure, a local binding — carries a within-file discriminator instead of a global moniker, and never joins across files. That is by design: it keeps the graph honest about what is genuinely part of your interface. If search cannot find something, ask whether it is exported at all.
The grammar belongs to the backend
Each language backend emits its own exact moniker grammar, pinned by that backend's fingerprint rather than by a cross-language spec. Practically, this means the shape of a Go moniker and a Rust moniker are not guaranteed to match, and the reliable way to get either is still search.