SmartMemory
Guides

Code Indexing

SmartMemory can parse and index entire code repositories, turning source code into searchable knowledge graph nodes. Classes, functions, routes, tests, and their relationships become first-class entities that you can query alongside your other memories.

How It Works

ingest_code() performs a multi-pass analysis of your repository:

  1. File collection -- walks the directory tree, collecting files by language.
  2. AST parsing -- extracts code entities (classes, functions, routes, tests) and relationships (imports, calls, inheritance) from each file.
  3. Cross-file resolution -- builds a symbol table to resolve import bindings across modules, so CALLS and IMPORTS edges point to the correct target nodes.
  4. Graph writing -- creates nodes and edges in the knowledge graph using bulk operations.
  5. Embedding generation -- generates vector embeddings for each entity so code symbols appear in search() results.
  6. Pattern seeding -- promotes class and function names into the EntityRuler pattern set, so future ingest() calls over natural-language text recognise references to your codebase.

Basic Usage

from smartmemory import SmartMemory

memory = SmartMemory()

# Index a Python repository
result = memory.ingest_code(
    directory="/path/to/my-project",
    repo="my-project",
)

print(f"Parsed {result.files_parsed} files")
print(f"Created {result.entities_created} entities, {result.edges_created} edges")
print(f"Generated {result.embeddings_generated} embeddings")
print(f"Completed in {result.elapsed_seconds}s")

Parameters

ParameterTypeDefaultDescription
directorystrrequiredAbsolute path to the repository root.
repostrrequiredShort repository identifier (e.g. "my-service"). Used as a namespace prefix on all generated node IDs.
languageslist[str]["python"]Languages to index. Pass ["python", "typescript"] to include .ts, .tsx, .js, and .jsx files.
commit_hashstr | NoneNoneGit commit SHA to attach. Auto-detected via git rev-parse HEAD when None. Pass "" to suppress auto-detection.
exclude_dirslist[str] | NoneNoneDirectory names to skip (e.g. ["node_modules", ".venv"]). Defaults include __pycache__, .git, .venv, venv, node_modules, .tox, .mypy_cache, .pytest_cache.

Multi-Language Example

result = memory.ingest_code(
    directory="/path/to/fullstack-app",
    repo="fullstack-app",
    languages=["python", "typescript"],
    exclude_dirs=["node_modules", "dist", ".venv"],
)

Entity Types

The parser extracts five entity types from source code:

Entity TypeDescriptionExample
moduleA source file (one per parsed file)smartmemory/code/parser.py
classClass definitionclass CodeParser
functionFunction or method definitiondef parse_file(...)
routeFastAPI/Express route handler@router.get("/health")
testTest function (pytest test_ prefix)def test_index_python_repo()

Each entity is assigned a deterministic ID in the format code::{repo}::{file_path}::{name}, making re-indexing idempotent.

Node Properties

Every code entity node carries these properties in the knowledge graph:

PropertyTypeAlways PresentDescription
item_idstryesDeterministic node ID (code::repo::path::name)
namestryesEntity name
entity_typestryesOne of: module, class, function, route, test
file_pathstryesRelative path from the repository root
line_numberintyesLine number where the entity is defined
repostryesRepository identifier
memory_typestryesAlways "code"
docstringstrif presentFirst 500 characters of the entity's docstring
decoratorsstrif presentComma-separated decorator names
basesstrif presentComma-separated base class names
http_methodstrroutes onlyHTTP method (GET, POST, etc.)
http_pathstrroutes onlyRoute path (/health, /memory/{id})
commit_hashstrif providedGit commit SHA at index time
indexed_atstryesISO timestamp of when the entity was indexed

Relationship Edges

The indexer creates five types of edges between code entity nodes:

Edge TypeMeaningExample
DEFINESA module defines a class/functionparser.py --DEFINES--> CodeParser
IMPORTSA file imports a symbol from another moduleindexer.py --IMPORTS--> CodeEntity
CALLSA function calls another functionindex() --CALLS--> parse_file()
INHERITSA class extends another classSqliteStore --INHERITS--> BaseStore
TESTSA test function tests a specific entitytest_parse_file() --TESTS--> parse_file()

Cross-file CALLS and IMPORTS edges are resolved through a two-pass symbol table that maps local import names to their target entity IDs.

Searching Code Entities

Indexed code entities are embedded and appear in standard search() results alongside other memory types:

# Find code related to "authentication middleware"
results = memory.search("authentication middleware", top_k=10)

for item in results:
    if item.memory_type == "code":
        print(f"{item.entity_type}: {item.name} ({item.file_path}:{item.line_number})")

Because code entities share the same vector space as all other memories, a search for "JWT token validation" can return both code entities (the actual implementation) and semantic memories (design decisions, documentation notes) in a single result set.

Incremental Updates

For adding or updating individual code entities without re-indexing an entire repository, use ingest_structured() with the code_entity schema:

memory.ingest_structured(
    {
        "name": "AuthMiddleware",
        "entity_type": "class",
        "file_path": "middleware/auth.py",
        "line_number": 42,
        "repo": "my-service",
        "docstring": "JWT authentication middleware for FastAPI.",
        "bases": ["BaseHTTPMiddleware"],
    },
    schema="code_entity",
)

This uses the CodeEntityHandler, which applies the INDEXED ingestion strategy with embeddings enabled. It is useful when:

  • A CI pipeline detects changed files and needs to update only those entities.
  • An external tool (linter, IDE plugin) produces structured code metadata.
  • You want to register code entities from languages the parser does not yet support.

Required Fields

The code_entity schema requires: name, entity_type, file_path, line_number, and repo. The entity_type must be one of: module, class, function, route, test.

Languages Supported

LanguageStatusFile ExtensionsNotes
PythonFull support.pyAST-based parsing. Extracts classes, functions, FastAPI routes, pytest tests, imports, calls, inheritance.
TypeScriptExperimental.ts, .tsx, .js, .jsxBasic entity extraction. Pass languages=["python", "typescript"] to enable.

IndexResult

The ingest_code() method returns an IndexResult dataclass:

@dataclass
class IndexResult:
    repo: str
    files_parsed: int = 0
    files_skipped: int = 0
    entities_created: int = 0
    edges_created: int = 0
    errors: list[str] = field(default_factory=list)
    elapsed_seconds: float = 0.0
    embeddings_generated: int = 0
    commit_hash: str = ""

Check result.errors after indexing to see any files that failed to parse (syntax errors, encoding issues). Failed files are skipped without aborting the run.

Pattern Seeding

After indexing, seed_patterns_from_code() runs automatically. It extracts {name: entity_type} pairs from the indexed entities and merges them into the workspace's EntityRuler pattern set.

This means that after you index a codebase, future ingest() calls over natural-language text will recognise references to your code symbols. For example, if you index a project containing class SmartGraph, then ingesting the text "The SmartGraph module handles all FalkorDB queries" will correctly identify SmartGraph as a named entity of type class.

On this page