NestJS backend for RememberNow - an automatically managed, graph-enabled, time-aware knowledge bank.
Install dependencies:
npm installFill out .env file (GEMINI_API_KEY is required):
cp .env.example .envMake sure Docker is running:
docker info| Command | What runs |
|---|---|
docker compose up -d |
Everything except Langfuse observability |
docker compose --profile observability up -d |
Everything, including observability |
npm run infra:dev:up |
Infra + observability (no app container, since dev runs it on host) |
npm run infra:test:up |
App deps only, no observability, uses .env.test (change default ports) |
Run app in container (easiest):
docker compose up -dRun app on host.
Also brings up Langfuse + MinIO + ClickHouse:
npm run prisma:generate && npm run infra:dev:up && npm run prisma:dev:deploy && npm run start:devWhen done developing for the day (preserves data):
npm run infra:dev:stopResume development with existing data:
npm run infra:dev:start && npm run start:devAfter editing prisma/schema.prisma (regenerate client + create a new migration):
npm run prisma:generate && npm run prisma:dev:migrateFull reset + infra restart (destroys all data):
npm run infra:dev:resetOr remove all data and containers manually.
npm run infra:dev:rmOnce dev infra is up, the following web UIs are available:
- Swagger UI: http://localhost:3333/api (requires the app to be running)
- Prisma Studio: http://localhost:5555 (requires
npm run prisma:studio) - Langfuse: http://localhost:3334
- MinIO console: http://localhost:9091
Installed automatically by npm install via Husky. On each commit, lint-staged runs ESLint (zero warnings allowed) and Prettier across staged TS/JS files, and Prettier across staged JSON/Markdown/YAML.
The Prisma client runs with the strictUndefinedChecks preview feature enabled. This means passing undefined to any field in data, where, take, orderBy, etc. throws at runtime instead of being silently ignored.
When you have a possibly-undefined value, guard at the call site - either use a conditional spread or Prisma.skip.
The openapi.json is auto-generated when you run npm run start:dev.
Make sure to commit changes when you modify routes/DTOs.
Unit tests:
npm run testE2E tests (.env.test file must be present. Change ports to not conflict with dev stack):
npm run test:e2eTest coverage:
npm run test:covThe anti-flaky test runner executes unit tests once, then runs e2e tests repeatedly to detect intermittent failures and race conditions. Useful for validating test reliability after infrastructure changes.
Run with default 15 iterations:
./anti-flaky-test.shRun with custom iteration count:
./anti-flaky-test.sh 30The runner will exit immediately on first failure and display the failing test output. Test infrastructure is set up once and torn down automatically on completion or interruption.
Langfuse captures full LLM traces - including prompts and outputs - and is only intended for use in development. It is off by default and never enabled on the hosted product.
To turn it on for local dev:
- Bring up the observability profile (
npm run infra:dev:upalready does this). - Open http://localhost:3334 and create an account + project (any name).
- In the project, go to Settings -> API Keys and create a new key pair.
- Add the resulting keys to your
.env:LANGFUSE_ENABLED=true LANGFUSE_PUBLIC_KEY=pk-lf-... LANGFUSE_SECRET_KEY=sk-lf-... - Restart
npm run start:dev. Traces should start appearing under the project's Traces tab.
When running the app inside the docker network instead of on the host, also set LANGFUSE_BASE_URL=http://langfuse-web:3000 (the in-network hostname). The default in .env.example points at the host-mapped port http://localhost:3334.
The knowledge graph pipeline in this project is a modified TypeScript port of Graphiti by Zep AI, adapted for this codebase for the following reasons:
- I need to implement a Graph Versioning system to prevent data loss due to agent misbehavior, which is impossible without direct code access.
- Graphiti couples tightly to specific providers. This port integrates with LangChain so any supported model can be swapped in without changing pipeline code.
- Graphiti maintains provider abstractions for its graph layer. Managed to make Graphiti work with just Postgres (pgvector + pgvectorscale for ANN search), so those abstractions are unnecessary and removing them adds room for enhancements.
- RememberNow is privacy-focused software. Depending on upstream code that cannot be audited, patched, or controlled introduces risk.
Approximate nearest-neighbor vector search is powered by pgvectorscale (PostgreSQL License) from Tiger Data, layered on top of pgvector. The knowledge-graph migration enables the vectorscale extension and builds StreamingDiskANN indexes (with SBQ compression and label-based filtering) over the knowledge graph's vector embeddings - see prisma/migrations/20260517000000_knowledge_graph/migration.sql.
The @Span and @Traceable decorators in src/observability/decorators/ (and their tests) are ported from nestjs-otel (Apache-2.0), with a local asLangfuseTrace option added.
RememberNow is licensed under Apache-2.0.