TypeScript
Install the TypeScript SDK and ingest and search a brain in under a minute.
Install
npm i -g @jeffs-brain/memory pnpm add -g @jeffs-brain/memory bun add -g @jeffs-brain/memory Requires Node >=20.
CLI quick start
memory init ./my-brain
memory ingest ./docs/hedgehogs.md --brain ./my-brain
memory search "where do hedgehogs live?" --brain ./my-brain
memory init creates a git-backed brain directory. memory ingest chunks a file, writes it to the brain, and upserts the chunks into the SQLite search index. memory search runs a hybrid BM25 + vector query when an embedder is configured, or BM25 alone otherwise.
See the CLI reference for every flag.
Programmatic use
Minimal BM25-only ingest and search, taken verbatim from examples/ts/hello-world/.
// SPDX-License-Identifier: Apache-2.0
import { readFile, mkdir } from 'node:fs/promises'
import { basename, resolve } from 'node:path'
import {
chunkMarkdown,
createFsStore,
createSearchIndex,
toPath,
type SqliteSearchIndexChunk,
} from '@jeffs-brain/memory'
const BRAIN_ID = 'hello-world'
async function main(): Promise<void> {
const brainRoot = resolve('./data', BRAIN_ID)
await mkdir(brainRoot, { recursive: true })
const store = await createFsStore({ root: brainRoot })
const index = await createSearchIndex({ dbPath: resolve(brainRoot, 'search.db') })
try {
const docPath = resolve('./docs/hedgehogs.md')
const raw = await readFile(docPath)
const storedPath = `raw/documents/${basename(docPath)}`
await store.batch({ reason: 'ingest' }, async (batch) => {
await batch.write(toPath(storedPath), raw)
})
const chunks = chunkMarkdown(raw.toString('utf8'))
const indexChunks: SqliteSearchIndexChunk[] = chunks.map((chunk) => ({
id: `${BRAIN_ID}:${basename(docPath)}:${chunk.ordinal}`,
path: storedPath,
ordinal: chunk.ordinal,
title: chunk.headingPath.join(' > '),
content: chunk.content,
}))
index.upsertChunks(indexChunks)
const results = index.searchBM25('where do hedgehogs live?', 3)
for (const [i, hit] of results.entries()) {
console.log(`${i + 1}. [${hit.score.toFixed(3)}] ${hit.chunk.content.slice(0, 120)}...`)
}
} finally {
await index.close()
await store.close()
}
}
main()
To run hybrid retrieval rather than BM25 alone, supply an Embedder and call createRetrieval instead of index.searchBM25. See retrieval for the full pipeline.
Next steps
- Memory stages: remember, extract, reflect, consolidate, recall.
- MCP integration: plug the brain into Claude Code or any MCP-capable agent.
- Examples: runnable end-to-end samples.