
Product
Introducing Repository Access Permissions and Custom Roles
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.
@kuindji/memory-domain
Advanced tools
Domain-driven memory engine with graph storage, embeddings, and semantic search
A domain-driven memory engine with graph storage, embeddings, and semantic search. Built on SurrealDB.
ClaudeCliAdapter (local claude CLI) and BedrockAdapter (Amazon Bedrock via the Anthropic SDK)onnxruntime-nodenpm install @kuindji/memory-domain
OnnxEmbeddingAdapter needs a BERT-family ONNX encoder and its vocab file. Fetch them with:
npx memory-domain-download-model # default: all-MiniLM-L6-v2 (~86 MB, mean-pooled)
npx memory-domain-download-model --model bge-small # BAAI/bge-small-en-v1.5 (~133 MB, CLS-pooled)
# or to a custom location:
npx memory-domain-download-model --dir ./my-models
By default MiniLM writes to ./.memory-domain/model/ and BGE-small writes to ./.memory-domain/model-bge-small/ relative to the current directory. new OnnxEmbeddingAdapter() defaults to the MiniLM path; point it elsewhere via new OnnxEmbeddingAdapter({ modelDir: "./my-models" }). BGE-small requires pooling: "cls" to match its training objective; MiniLM stays on the default "mean".
import {
MemoryEngine,
topicDomain,
ClaudeCliAdapter,
OnnxEmbeddingAdapter,
} from "@kuindji/memory-domain";
const engine = new MemoryEngine();
await engine.initialize({
connection: "surrealkv:///tmp/memories/db", // embedded; or "ws://localhost:8000" for a remote SurrealDB
namespace: "my_app",
database: "memories",
llm: new ClaudeCliAdapter(),
embedding: new OnnxEmbeddingAdapter(),
});
await engine.registerDomain(topicDomain);
// Ingest a memory
await engine.ingest("TypeScript 5.5 introduces inferred type predicates");
// Search
const results = await engine.search("TypeScript features");
// Ask a question
const answer = await engine.ask("What do I know about TypeScript?");
import { BedrockAdapter } from "@kuindji/memory-domain";
const llm = new BedrockAdapter({
modelId: "eu.anthropic.claude-sonnet-4-6",
region: "eu-west-2",
profile: "my-aws-profile", // or pass `credentials`, or omit to use the default chain
modelLevels: {
low: "eu.anthropic.claude-haiku-4-5",
medium: "eu.anthropic.claude-sonnet-4-6",
high: "eu.anthropic.claude-opus-4-6-v1",
},
});
BedrockAdapter implements the same LLMAdapter interface as ClaudeCliAdapter, so it's a drop-in swap.
The package includes CLI tools:
# CLI
npx memory-domain --help
npx memory-domain ingest --text "Some memory to store"
npx memory-domain search --query "find something"
# Interactive TUI
npx memory-domain-tui
The CLI and TUI look for a memory-domain.config.ts (or .js / .mjs) file in your project root. The module must default-export a fully-initialized MemoryEngine instance — use top-level await to initialize and register domains before exporting:
import {
MemoryEngine,
topicDomain,
ClaudeCliAdapter,
OnnxEmbeddingAdapter,
} from "@kuindji/memory-domain";
const engine = new MemoryEngine();
await engine.initialize({
connection: "surrealkv:///tmp/memories/db",
namespace: "default",
database: "memory",
llm: new ClaudeCliAdapter(),
embedding: new OnnxEmbeddingAdapter(),
});
await engine.registerDomain(topicDomain);
export default engine;
EngineConfig.adapter accepts a ConnectionAdapter that resolves to a SurrealDB connection string at startup and can optionally persist the database back on engine.close(). The package ships three:
PassthroughAdapter(connectionString) — just returns the string you gave it. Use when you already have a SurrealDB URL (remote server, file path, in-memory).FileConnectionAdapter({ file, localDir?, save? }) — extracts a local .tar.gz archive to a working directory and exposes it as surrealkv://<dir>/db. Set save: true to recompress on close. Ideal for shipping prebuilt KBs alongside your code.S3ConnectionAdapter({ bucket, key, region, profile?, credentials?, save? }) — same shape but fetches/uploads the archive from S3.DirectoryConnectionAdapter({ path }) — opens a pre-extracted path/db/ directory in place. Read-intended; save() is a no-op. Use when a container image bakes the DB alongside the code and you want to skip tar extraction on cold start. Do not open the same path twice in one process — SurrealKV expects exclusive access.import { MemoryEngine, FileConnectionAdapter, BedrockAdapter } from "@kuindji/memory-domain";
const engine = new MemoryEngine();
await engine.initialize({
adapter: new FileConnectionAdapter({ file: "./kb.tar.gz" }),
namespace: "my_app",
database: "kb",
llm: new BedrockAdapter({
modelId: "eu.anthropic.claude-sonnet-4-6",
region: "eu-west-2",
profile: "my-aws-profile",
}),
});
The CLI is one of several transports over a shared command dispatcher. You can use memory-domain as a library to serve the same command surface over a Lambda, HTTP server, or any other runtime without shelling out.
import {
MemoryEngine,
DirectoryConnectionAdapter,
BedrockAdapter,
OnnxEmbeddingAdapter,
createKbDomain,
createLambdaAdapter,
} from "@kuindji/memory-domain";
// Construct once at module scope; reused across warm invocations.
const handlerPromise = (async () => {
const engine = new MemoryEngine();
await engine.initialize({
adapter: new DirectoryConnectionAdapter({ path: "/var/task/kb" }),
namespace: "my_app",
database: "business",
llm: new BedrockAdapter({
modelId: "eu.anthropic.claude-sonnet-4-6",
region: "eu-west-2",
}),
embedding: new OnnxEmbeddingAdapter({ modelDir: "/var/task/kb/model" }),
});
await engine.registerDomain(createKbDomain());
return createLambdaAdapter(engine); // defaults to the read-only profile
})();
export const handler = async (event: { command: string; args: string[] }) => {
const lambdaHandler = await handlerPromise;
return lambdaHandler(event);
};
The default profile exposes the read-side commands: search, build-context, memory, graph, skill, domains, domain. Pass { profile: "full" } to expose every command, or { profile: [...] } for a custom allow list. The returned DispatchResult carries both the raw output (structured data) and rendered (a pre-rendered JSON or pretty string), so callers can use whichever form they need.
Invocation shape: event.args is the argv tail including flags, e.g. { command: "search", args: ["query text", "--limit", "5"] }. Flags must be encoded as argv strings, matching the CLI's input contract.
Lifecycle: createLambdaAdapter never calls engine.close(). Construct the engine once at module scope and rely on Lambda's execution-environment reuse. Cold-start engine-init errors propagate out of engine.initialize() so Lambda marks the container as failed; per-invocation errors resolve as { ok: false, error: { code, message } }.
@surrealdb/node engine (default, via a surrealkv:// connection string or one of the bundled connection adapters) or a running SurrealDB server reached over ws:// / http://MIT
FAQs
Domain-driven memory engine with graph storage, embeddings, and semantic search
We found that @kuindji/memory-domain demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.

Product
Socket MCP now lets AI assistants review org alerts, investigate threats using the Socket threat feed, and inspect package files in addition to dependency scoring.

Product
Socket Firewall blocks malicious VS Code and Open VSX extensions before install, protecting developers from compromised editor marketplaces.