Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Effectful-Tech/clanka/llms.txt

Use this file to discover all available pages before exploring further.

The SemanticSearch module indexes a codebase with vector embeddings and exposes a similarity search interface. It handles initial indexing on startup, incremental updates when files change, and a periodic re-index schedule — all transparently within the Effect runtime.

SemanticSearch service

export class SemanticSearch extends Context.Service<
  SemanticSearch,
  {
    search(options: {
      readonly query: string
      readonly limit: number
    }): Effect.Effect<string>
    updateFile(path: string): Effect.Effect<void>
    removeFile(path: string): Effect.Effect<void>
  }
>()("clanka/SemanticSearch/SemanticSearch") {}
The service is a standard Effect Context.Service. Obtain it from context with yield* SemanticSearch or use the layer constructor described below to provide it. Run a similarity query against the indexed embeddings and return the best matching code chunks.
query
string
required
Natural-language description of what you are looking for.
limit
number
required
Maximum number of chunks to return.
Returns: Effect<string> — the matching chunk contents joined with double newlines. The initial index run must complete before the first search resolves; subsequent calls are not blocked.

updateFile

Re-index a single file. All existing embeddings for that path are removed and new ones are computed from the current file content.
path
string
required
Path to the file, relative to the root directory supplied to layer.
Returns: Effect<void>. Resolves immediately if the path falls outside the configured root or the file has no meaningful content.
The writeFile, renameFile, and applyPatch tools in AgentTools call maybeUpdateFile automatically. You only need to call updateFile directly when managing the index outside of those tools.

removeFile

Remove all embeddings for a file path from the index.
path
string
required
Path to the file, relative to the root directory.
Returns: Effect<void>.

SemanticSearch.layer

export const layer: (options: {
  readonly directory: string
  readonly database?: string | undefined
  readonly embeddingBatchSize?: number | undefined
  readonly embeddingRequestDelay?: Duration.Input | undefined
  readonly concurrency?: number | undefined
  readonly chunkMaxCharacters?: number | undefined
}) => Layer.Layer<
  SemanticSearch,
  SqlError.SqlError | SqliteMigrator.MigrationError | PlatformError.PlatformError,
  | EmbeddingModel.EmbeddingModel
  | Path.Path
  | ChildProcessSpawner.ChildProcessSpawner
  | FileSystem.FileSystem
  | EmbeddingModel.Dimensions
>
The primary constructor for SemanticSearch. Returns a scoped Layer that, when mounted, immediately starts an initial full-codebase index and schedules a re-index every 3 minutes.

Options

directory
string
required
Absolute path to the root of the codebase to index.
database
string
Path to the SQLite database file used to persist embeddings. Defaults to ".clanka/search.sqlite" relative to the process working directory.
embeddingBatchSize
number
Maximum number of embedding requests batched into a single model call. Defaults to 300.
embeddingRequestDelay
Duration.Input
Delay between batched embedding requests. Defaults to Duration.millis(50).
concurrency
number
Number of chunk embedding operations to run in parallel during indexing. Defaults to 2000.
chunkMaxCharacters
number
Maximum character length per code chunk. Defaults to 10000. Chunks exceeding this limit are split further.

Layer requirements

The layer requires the following services to be provided by the caller:
  • EmbeddingModel.EmbeddingModel — produces embedding vectors from text.
  • EmbeddingModel.Dimensions — the dimensionality of the embedding vectors.
  • Path.Path — Effect platform path service.
  • ChildProcessSpawner.ChildProcessSpawner — used internally by CodeChunker to enumerate files via rg.
  • FileSystem.FileSystem — used internally by CodeChunker to read file content.
The layer may fail during construction with SqlError, MigrationError, or PlatformError if the database cannot be initialised or the root directory cannot be read.

Auto-indexing behaviour

When the layer is mounted it:
  1. Runs an immediate full-codebase index in a background fiber.
  2. The first search call waits for that initial index fiber to complete.
  3. After the initial index, a recurring fiber re-indexes the full codebase every 3 minutes, skipping any chunk whose embedding hash is already stored.

Utilities

makeEmbeddingResolver

export const makeEmbeddingResolver: (
  resolver: EmbeddingModel.Service["resolver"],
  options: {
    readonly embeddingBatchSize?: number | undefined
    readonly embeddingRequestDelay?: Duration.Input | undefined
  },
) => EmbeddingModel.Service["resolver"]
Wraps a raw embedding resolver with batching and delay middleware. Used internally by SemanticSearch.layer but exported for cases where you need a pre-configured resolver outside of the layer.
resolver
EmbeddingModel.Service['resolver']
required
The base resolver from an EmbeddingModel service instance.
embeddingBatchSize
number
Batch size. Defaults to 300.
embeddingRequestDelay
Duration.Input
Inter-batch delay. Defaults to Duration.millis(50).

chunkEmbeddingInput

export const chunkEmbeddingInput: (chunk: CodeChunker.CodeChunk) => string
Converts a CodeChunk into the text string that is sent to the embedding model. The output includes a YAML-style frontmatter header followed by the chunk content with 1-based line numbers prepended to each line. Output format:
---
file: src/AgentTools.ts
name: AgentTools
type: variable
parent: namespace Clanka
---

74: export const AgentTools = Toolkit.make(
75:   Tool.make("readFile", {
...
The frontmatter fields name, type, and parent are omitted when the corresponding chunk fields are undefined.

Build docs developers (and LLMs) love