Vol. 001 Jeffs Brain·Documentation

Source start/typescript

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