What “symbol” means in NCI
A symbol is one merged graph row — one declaration in the model the agent queries. Classes own their members. Overloads can either fuse into one row or stay as separate rows, depending on how their normalised signatures collide. The columns below are the public ones you can read with nci query and nci sql.
Anatomy
| Column | What it stores |
|---|---|
symbol_id | Integer row id. Use it for SQL joins to dependency tables. |
id | Stable string handle, scoped to the indexed package version. The handle nci query show / snippet / overloads takes; matched by symbol_dependencies.to_symbol_id_text. |
package_id | Indexed package install this symbol belongs to. |
name | Short symbol name. Nested members may carry dotted segments — do not infer the lexical parent from the string when parent_symbol_id is set. |
kind / kind_name | Numeric and string AST kinds (FunctionDeclaration, InterfaceDeclaration, MethodSignature, ExportDeclaration, …). declare const … = … is VariableStatement, not TypeAliasDeclaration. |
signature | Declaration signature text; merged overloads can appear as one fused multi-block string. |
js_doc | JSDoc verbatim, when present. |
file_path | Primary declaration site, package-relative. May contain index encoding tokens (nci_external / up) when the declaration sits outside the indexed package root. |
source_package_name | The npm package that owns the declaration. Matches --source-package. |
source_package_version | Semver of the source package — only when source = indexed package; usually NULL for external declarations. |
source_file_path | Path inside the owning package. NOT NULL. Use this for disk navigation, not raw file_path. |
parent_symbol_id | Immediate lexical containment parent (a method’s class, etc.). Not a type-use edge. |
enclosing_module_declaration_id | Id of the surrounding ModuleDeclaration / namespace block. Not always equal to parent_symbol_id. |
entry_visibility_json | JSON list of package-relative entry / barrel paths through which this symbol is reachable on the public export surface (types / exports). Distinct from file_path. |
merge_provenance_json | How the row was merged: merge_scope, identical_fold, overload_key. Pair with signature + kind_name when interpreting overloads vs. re-exports. |
visibility | JSDoc API tag (@public, @internal, @alpha, @beta) — separate from is_internal. |
is_internal | Export-graph reachability. 1 = not on the public export path from package entries. Not “skip this row”. |
is_global_augmentation | 1 if the symbol came from declare global { … }. |
is_inherited | 1 for synthesised inherited members; see symbol_inherited_from_sources for contributing bases. |
is_type_only / symbol_space | Distinguish type-only declarations from value-namespace symbols. |
Path encoding (__nci_external__, __up__)
When a declaration resolves outside the indexed package root, file_path does not use raw ../ segments. Instead it uses canonical tokens — __nci_external__ plus one __up__ segment per parent hop. Treat those as stable SQLite keys, not filesystem paths.
For real disk access, combine source_package_name + source_file_path with the install layout. If that still does not yield a real file, fall back to nci query snippet / nci query show — those return cite-ready text without needing a path.
Three id shapes
Worked example: a class’s members
Take the id from that JSON envelope and feed it into query overloads to see every sibling row, or join in SQL on parent_symbol_id to walk a class’s declared members.
SELECT m.name, m.signature FROM symbols m JOIN symbols c ON c.symbol_id = m.parent_symbol_id JOIN packages p ON p.package_id = c.package_id WHERE c.name = 'ZodObject' AND c.kind_name = 'ClassDeclaration' AND p.name = 'zod' ORDER BY m.name;