Thank you for your interest in contributing! Engram is an open-source project and every contribution matters — from a typo fix to a new adapter for an AI tool you use.
- Bug reports — open an issue with reproduction steps
- Feature requests — describe the use case, not just the feature
- Pull requests — code changes, with tests where applicable
- New adapters — connect Engram to a new AI tool or platform
- Documentation — improvements, translations, examples
- Performance — benchmarks, profiling, optimization
git clone https://github.com/ayvazyan10/engram
cd engram
pnpm install
pnpm turbo run buildRun the test suite:
pnpm turbo run testStart the API server and dashboard for local development:
# Terminal 1 — API server
ENGRAM_DB_PATH=./packages/core/engram.db \
node apps/server/dist/index.js
# Terminal 2 — Dashboard
pnpm --filter @engram-ai-memory/web dev-
pnpm turbo run buildpasses with no errors -
pnpm turbo run testpasses - New functionality has tests (
src/**/*.test.ts) - Database schema changes use
drizzle-kit generate→drizzle-kit migrate(neverpush) - Docs updated if public behavior changed
feature/description new functionality
fix/description bug fix
docs/description documentation only
refactor/description no behavior change
adapter/name new integration adapter
Follow Conventional Commits:
feat(core): add importance decay on recall
fix(server): correct socket.io namespace initialization
feat(adapter): add LM Studio proxy adapter
docs: improve MCP setup guide
refactor(mcp): simplify tool registration pattern
Adapters live in adapters/. The simplest adapter needs two things:
- Recall — call
POST /api/recallwith the user query before the AI responds - Store — call
POST /api/memoryafter the AI responds to persist the exchange
See adapters/ollama/ for a proxy pattern and adapters/openclaw/ for a library pattern.
// Minimal adapter pattern
const context = await fetch('http://localhost:4901/api/recall', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: userMessage, maxTokens: 2000 }),
}).then(r => r.json()).then(d => d.context).catch(() => '');
// inject `context` into system prompt, run your AI
await fetch('http://localhost:4901/api/memory', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content: `User: ${userMessage}\nAssistant: ${response}`, type: 'episodic' }),
}).catch(() => {});- TypeScript strict mode (
strict: truein tsconfig) - No
anytypes where avoidable - Prefer explicit return types on exported functions
- No default exports in library packages (named exports only)
ESLint runs via pnpm turbo run lint. Fix issues before opening a PR.
| Label | Meaning |
|---|---|
bug |
Something is broken |
enhancement |
New feature or improvement |
adapter |
New AI tool integration |
good first issue |
Suitable for first-time contributors |
help wanted |
Needs community input |
docs |
Documentation changes |
performance |
Speed or memory improvements |
Open a GitHub Discussion — not an issue — for questions, ideas, and general conversation.