SwiftKG
Knowledge graph for Swift codebases -- deterministic AST extraction, hybrid semantic + structural search.
Overview
SwiftKG builds a queryable knowledge graph from Swift source using:
- tree-sitter for deterministic, parser-level AST extraction (no LLM inference during indexing)
- SQLite for the structural graph (nodes, edges, provenance)
- sqlite-vec for the semantic vector index (embeddings via
BAAI/bge-small-en-v1.5) - Hybrid retrieval: semantic seed → graph hop expansion → lexical re-ranking
It needs no Swift toolchain, no Xcode, and no buildable project. Point it at any checkout, on macOS or on Linux CI, and it indexes.
What Swift makes different
Three things about Swift are not cosmetic differences from the Python and TypeScript modules in this fleet, and they shape the whole graph.
Inheritance and conformance are written identically. : Base, Proto gives
no syntactic signal about which is which:
final class DiskStorage: Storage<Data> {} // superclass
struct Point: Equatable, Hashable {} // two protocols
class Storage<T>: NSObject, Repository {} // superclass, then protocol
SwiftKG runs two passes. The first builds a repository-wide table of every
declared type and its kind; the second resolves each specifier against it, so
a protocol target becomes CONFORMS and a class or actor target becomes
INHERITS. When the target is external — NSObject, Codable, anything from
a dependency — it falls back to the language's own rule: only a class or actor
may have a superclass, and it must be written first.
There are no per-file imports within a module. Every file in a target sees
every other file's declarations without an import statement. That makes the
repository the correct resolution scope rather than an approximation of one,
so calls and type references resolve across files. A name declared twice
resolves to nothing rather than to an arbitrary one of the two — an honest
sym: stub beats a confidently wrong edge.
Extensions are a unit of authorship. A type's conformances and much of its
behaviour routinely live in an extension in a different file. Each extension
gets its own node and an EXTENDS edge to the type, with members qualified
under the type (Point.scaled), so swiftkg can answer "where is the rest of
this type" without losing where the code actually is. Since it is idiomatic to
write one extension per conformance, an extension's own ID carries its
conformance list (ext:…:Point+Codable) rather than colliding on the type name.
Swift also states access level with a keyword, so public / open /
internal / private is recorded as a fact rather than guessed from a naming
convention. The public-API report, the centrality penalty for private symbols,
and explain's reasoning about zero-caller declarations all read it directly.
Node types
| Kind | Description |
|---|---|
module |
Every indexed .swift file |
class |
Class declaration |
struct |
Struct declaration |
enum |
Enum declaration |
protocol |
Protocol declaration |
actor |
Actor declaration |
extension |
Extension declaration |
function |
Free function at file scope |
method |
Function, initializer, deinitializer or subscript inside a type |
property |
Stored or computed property, enum case, or file-scope let/var |
typealias |
Type alias, and associatedtype inside a protocol |
symbol |
Unresolved import or call stub |
Edge types
| Relation | Description |
|---|---|
CONTAINS |
module → type/function, type → member |
IMPORTS |
module → sym:<Module> (a Swift import names a module, not a file) |
CALLS |
function/method → function, method, or type initializer |
INHERITS |
class or actor → superclass |
CONFORMS |
type or extension → protocol |
EXTENDS |
extension → the type it extends |
Quick start
pip install swift-kg
# First-time setup (downloads model, builds graph, installs hooks, snapshots)
swiftkg init --repo /path/to/swift-repo
# Build the KG for a Swift repo
swiftkg build --repo /path/to/swift-repo
# Query
swiftkg query "networking layer"
swiftkg pack "request error handling" --hop 2
# Understand the repository
swiftkg analyze /path/to/swift-repo
swiftkg centrality --top 20
swiftkg explain "proto:Sources/Networking/Client.swift:HTTPClienting"
build wipes and rebuilds; update upserts without wiping. The split is
deliberate — a rebuild is correct after renames or deletions, where an upsert
leaves phantom nodes behind, so the safe operation is the bare verb and the
surprising one has to be asked for by name.
MCP tools
swiftkg mcp --repo /path/to/swift-repo exposes 21 tools. Two exist only in
this module:
| Tool | Purpose |
|---|---|
type_hierarchy(node_id) |
Conformers, subclasses, extensions and declared supertypes of one type, together — for a Swift type these are one question |
public_api(module_path, limit) |
The declared public / open surface, read from access levels |
The rest match the fleet: graph_stats, query_codebase, pack_snippets,
callers, get_node, list_nodes, find_node, centrality,
bridge_centrality, framework_nodes, find_definition_at, analyze_repo,
explain, rank_nodes, query_ranked, explain_rank, snapshot_list,
snapshot_show, snapshot_diff.
See docs/MCP.md for client configuration.
Snapshots & git hook
swiftkg snapshot save records graph metrics under .swiftkg/snapshots/, and
swiftkg install-hooks installs a pre-commit hook that keeps them current.
Alongside the shared metrics, SwiftKG records what actually characterises a
Swift codebase: counts by type kind, conformance and inheritance counts, and
extensions-per-type — how much behaviour is declared away from the type it
belongs to.
Snapshots, not per-node timestamps, are how a code KG answers temporal questions. Git already owns when the code changed.
Python API
from swift_kg import SwiftKG
with SwiftKG(repo_root="/path/to/swift-repo") as kg:
kg.build(wipe=True)
result = kg.query("networking layer", k=8)
pack = kg.pack("request error handling")
pack.save("context.md")
protocol_id = "proto:Sources/Networking/Client.swift:HTTPClienting"
kg.conformers(protocol_id) # every conforming type and extension
kg.subclasses(class_id) # direct subclasses
kg.extensions_of(type_id) # extensions, wherever they are declared
Configuration
When the target repository has a pyproject.toml, SwiftKG reads
[tool.swiftkg]:
[tool.swiftkg]
include = ["Sources"] # top-level dirs to index (unset = all)
exclude = ["Vendor"] # extra dirs to skip at every depth
Most Swift repositories have no pyproject.toml, which is fine: with no
config, everything is indexed. .build, .swiftpm, DerivedData, Pods,
Carthage, xcuserdata and *.xcodeproj / *.xcworkspace bundles are always
skipped.
Architecture
Swift source ─► tree-sitter ─► pass 1: symbol table
└► pass 2: NodeSpec / EdgeSpec
│
├─► SQLite (authoritative graph)
└─► sqlite-vec (semantic index)
│
hybrid query ◄────┘
│
CLI · MCP server · Python API
Everything below the extractor — persistence, indexing, hybrid retrieval,
snippet packing, snapshots — comes from
kgmodule-utils. This package
implements the Swift-specific layer and nothing else.
Status
The visualizers (swiftkg viz, viz3d, viz-timeline) are registered and
report that they are not yet available; see the CHANGELOG's Unreleased
section. Everything else is complete.
Author
Eric G. Suchanek, PhD — Flux-Frontiers
Citation
If you use SwiftKG in your research or project, please cite it:
Suchanek, E. G. (2026). SwiftKG: Semantic Knowledge Graph for Swift Codebases (Version 0.4.0) [Software]. Flux-Frontiers. https://doi.org/10.5281/zenodo.22759432
@software{suchanek_swift_kg,
author = {Suchanek, Eric G.},
title = {{SwiftKG}: Semantic Knowledge Graph for Swift Codebases},
version = {0.4.0},
year = {2026},
publisher = {Flux-Frontiers},
doi = {10.5281/zenodo.22759432},
url = {https://github.com/Flux-Frontiers/swift_kg},
}
Full citation metadata in CITATION.cff.
License
Elastic License 2.0. See
LICENSE.
Release files for swift-kg 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| swift_kg-0.4.0.tar.gz | 105.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| swift_kg-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 221.6 kB
Release files / swift_kg-0.4.0.tar.gz
| Download URL | swift_kg-0.4.0.tar.gz |
|---|---|
| Size | 105.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6b084d211d7be0fbf8941744398ceb86ede70c620e6eecf3e5a23f2059a3b0fc
|
|
BLAKE2b-256 checksum How to use checksums |
b04d33be94fffed5b4d32c0b7232f47e48c905ea4d6745060975fe8f3643e4a8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency logRelease files / swift_kg-0.4.0-py3-none-any.whl
| Download URL | swift_kg-0.4.0-py3-none-any.whl |
|---|---|
| Size | 116.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0e1a2113af7c941a9b3df14f6c359f64e1bf106c3da1c229b91359e3f7b1fa52
|
|
BLAKE2b-256 checksum How to use checksums |
bceeb95a9d10be4dd4e5dfb1849e79d579ff468cf5f739595e760ee305e36f47
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency log