Crux
API Reference@crux/core

Crux Store

Low-level store utilities, keyspace helpers, and compatibility exports.

import { inMemoryCruxStore, keySpace, matchesFilter } from '@crux/core/store'
import type {
  CruxStore, JsonObject, StoreEntry, ListOptions, ListResult,
  ScoredEntry, SparseVector, VectorSearchOptions, VectorSearchQuery, StoreEvent, StoreSetEvent, StoreDeleteEvent,
  EmbedFn, ToolConfig,
} from '@crux/core/store'

Overview

Use @crux/core/storage for new application code. It exposes the canonical DataStore, VectorStore, and BlobStore interfaces.

@crux/core/store remains the low-level module for store utilities such as keySpace, filtering helpers, and existing adapter compatibility exports.

CruxStore Interface

MethodSignatureDescription
get(key: string) => Promise<JsonObject | null>Get a value by key. Returns null if not found.
set(key: string, value: JsonObject, options?) => Promise<void>Set a value. Creates or overwrites.
delete(key: string) => Promise<void>Delete a key. No-op if not found.
list(prefix: string, options?) => Promise<ListResult>List entries whose keys start with prefix. Sorted by updatedAt descending.
vectorSearch?(embedding: number[], options?) => Promise<ScoredEntry[]>Optional. Search by vector similarity.
searchVectors?(query: VectorSearchQuery) => Promise<ScoredEntry[]>Optional. Search by dense, sparse, or hybrid vector query.
subscribe?(callback: (event: StoreEvent) => void) => () => voidOptional. Subscribe to store changes. Returns unsubscribe function.
supportsTtl?() => booleanOptional. Whether the store supports TTL-based auto-expiry.

set(key, value, options?)

The optional options parameter accepts:

FieldTypeDescription
ttlnumber?Time-to-live in milliseconds. After this duration, get() returns null. Check supportsTtl() first.

list(prefix, options?)

Results are sorted by value.updatedAt descending (newest first). Supports pagination and filtering.

vectorSearch(embedding, options?)

Reads value.embedding (a number[]) from stored entries and ranks by cosine similarity. Returns empty if no entries have embeddings. Optional -- stores without vector capabilities can omit this.

searchVectors(query)

Use searchVectors() when your store supports sparse-only or hybrid retrieval.

type SparseVector = {
  indices: number[]
  values: number[]
}

type VectorSearchQuery = {
  dense?: number[]
  sparse?: SparseVector
  fusion?: 'rrf' | 'dbsf'
  limit?: number
  threshold?: number
  filter?: Record<string, unknown>
}

Rules:

  • dense-only stores may implement only vectorSearch()
  • sparse-only queries require searchVectors({ sparse })
  • hybrid queries require searchVectors({ dense, sparse })
  • unsupported query modes should throw explicitly rather than silently degrading

subscribe(callback)

Returns an unsubscribe function. Events are discriminated unions -- narrow on event.type to access value (only present on 'set').

inMemoryCruxStore()

Create an in-memory CruxStore backed by a Map. All data lives in process memory and is lost on restart. Supports vectorSearch() (linear scan), subscribe() (synchronous notifications), and supportsTtl().

Use for: test suites, local development, rapid prototyping. Not for production.

import { inMemoryCruxStore } from '@crux/core/store'

const store = inMemoryCruxStore()
await store.set('plan:abc', { title: 'My Plan', version: 1, updatedAt: Date.now() })
const plan = await store.get('plan:abc')

keySpace

Centralized store key namespace registry. All CruxStore key patterns in one place. Modules import key builders from here instead of scattering string literals.

Each namespace provides:

  • key(...) -- build a full key from identifiers
  • prefix -- the constant prefix for list/scan operations
import { keySpace } from '@crux/core/store'

// Build a key
const key = keySpace.plan.key('abc')         // 'plan:abc'
const key = keySpace.flow.key('flow-123')    // 'crux:flow:flow-123'

// Use prefix for listing
const result = await store.list(keySpace.plan.prefix)  // 'plan:'

Registered Namespaces

NamespaceKey FormatExample
keySpace.planplan:{id}plan:abc
keySpace.taskListtasklist:{id}tasklist:abc
keySpace.tasktask:{listId}:{taskId}task:abc:task-1
keySpace.flowcrux:flow:{id}crux:flow:flow-123
keySpace.signalcrux:signal:{flowId}:{name}crux:signal:flow-123:approve
keySpace.blackboardblackboard:{id}blackboard:shared

ListOptions

FieldTypeDescription
limitnumber?Maximum number of entries to return
cursorstring?Key of the last seen entry for pagination
filterRecord<string, unknown>?Filter by top-level value fields. Exact match semantics. null matches missing or explicitly null fields.

ListResult

FieldTypeDescription
entriesStoreEntry[]Entries matching the query
cursorstring?Cursor for the next page. undefined when no more pages.

StoreEntry

FieldTypeDescription
keystringThe unique key
valueJsonObjectThe stored value

ScoredEntry

Extends StoreEntry with a similarity score from vector search.

FieldTypeDescription
keystringThe unique key
valueJsonObjectThe stored value
scorenumberCosine similarity score (0-1)

VectorSearchOptions

FieldTypeDescription
limitnumber?Max results. Default: 10.
thresholdnumber?Min similarity score (0-1). Default: 0.
filterRecord<string, unknown>?Filter by value fields. Same semantics as ListOptions.filter.

VectorSearchQuery

FieldTypeDescription
densenumber[]?Dense query vector
sparseSparseVector?Sparse query vector
fusion'rrf' | 'dbsf'?Hybrid fusion strategy for capable stores
limitnumber?Max results
thresholdnumber?Min score
filterRecord<string, unknown>?Top-level value filter

StoreEvent

Discriminated union of store change events. Narrow on event.type.

VariantTypeFieldsDescription
StoreSetEvent'set'key, value, timestampA value was set
StoreDeleteEvent'delete'key, timestampA key was deleted
store.subscribe?.((event) => {
  if (event.type === 'set') {
    console.log('Updated:', event.key, event.value)
  } else {
    console.log('Deleted:', event.key)
  }
})

JsonObject

type JsonObject = Record<string, unknown>

All store values are this shape -- a JSON-serializable object.

Implementations

StorePackageUse Case
inMemoryCruxStore()@crux/core/storeTesting, development, prototyping
cruxConvexStore()@crux/convexProduction with Convex backend
cruxUpstashStore()@crux/upstashServerless with Upstash Redis/Vector

Types

import type {
  CruxStore, JsonObject, StoreEntry,
  ListOptions, ListResult,
  ScoredEntry, VectorSearchOptions,
  StoreEvent, StoreSetEvent, StoreDeleteEvent,
  EmbedFn, ToolConfig,
} from '@crux/core/store'

On this page