{"id":50293871,"url":"https://github.com/swiftj/cortex","last_synced_at":"2026-05-28T07:32:42.633Z","repository":{"id":331542730,"uuid":"1127454505","full_name":"swiftj/cortex","owner":"swiftj","description":"A local-first MCP memory server for Claude Code with hybrid vector + lexical search","archived":false,"fork":false,"pushed_at":"2026-01-10T01:32:37.000Z","size":107,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-10T23:36:42.728Z","etag":null,"topics":["ai","claude","embeddings","golang","llm","mcp","memory","pgvector","postgresql"],"latest_commit_sha":null,"homepage":"https://github.com/swiftj/cortex#readme","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/swiftj.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-03T23:14:19.000Z","updated_at":"2026-01-10T01:32:41.000Z","dependencies_parsed_at":"2026-01-11T01:02:53.164Z","dependency_job_id":null,"html_url":"https://github.com/swiftj/cortex","commit_stats":null,"previous_names":["swiftj/cortex"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/swiftj/cortex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swiftj%2Fcortex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swiftj%2Fcortex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swiftj%2Fcortex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swiftj%2Fcortex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/swiftj","download_url":"https://codeload.github.com/swiftj/cortex/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swiftj%2Fcortex/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33599465,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-28T02:00:06.440Z","response_time":99,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","claude","embeddings","golang","llm","mcp","memory","pgvector","postgresql"],"created_at":"2026-05-28T07:32:37.587Z","updated_at":"2026-05-28T07:32:42.626Z","avatar_url":"https://github.com/swiftj.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cortex\n\n**A local-first MCP memory server for Claude Code** — Persistent memory for AI agents with hybrid vector + lexical search.\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/swiftj/cortex/releases\"\u003e\u003cimg src=\"https://img.shields.io/badge/dynamic/regex?url=https%3A%2F%2Fraw.githubusercontent.com%2Fswiftj%2Fcortex%2Fmain%2FVERSION\u0026search=%5E%5B%5E%5Cn%5D%2B\u0026style=flat-square\u0026label=VERSION\u0026color=olive\" alt=\"Version\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://go.dev/\"\u003e\u003cimg src=\"https://img.shields.io/badge/Go-1.24%2B-00ADD8?style=flat-square\u0026logo=go\u0026logoColor=white\" alt=\"Go\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/swiftj/cortex\"\u003e\u003cimg src=\"https://img.shields.io/badge/macOS-000000?style=flat-square\u0026logo=apple\u0026logoColor=white\" alt=\"macOS\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/swiftj/cortex\"\u003e\u003cimg src=\"https://img.shields.io/badge/Linux-FCC624?style=flat-square\u0026logo=linux\u0026logoColor=black\" alt=\"Linux\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-MIT-gray?style=flat-square\" alt=\"License\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/swiftj/cortex\"\u003e\u003cimg src=\"https://img.shields.io/badge/AI-Multi--Provider-E91E8C?style=flat-square\" alt=\"AI Multi-Provider\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://claude.ai/code\"\u003e\u003cimg src=\"https://img.shields.io/badge/Claude%20Code-Compatible-CD6155?style=flat-square\" alt=\"Claude Code Compatible\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/pgvector/pgvector\"\u003e\u003cimg src=\"https://img.shields.io/badge/PostgreSQL-pgvector-4169E1?style=flat-square\u0026logo=postgresql\u0026logoColor=white\" alt=\"PostgreSQL pgvector\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/swiftj/cortex\"\u003e\u003cimg src=\"https://img.shields.io/badge/Docker-Ready-2496ED?style=flat-square\u0026logo=docker\u0026logoColor=white\" alt=\"Docker Ready\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## Features\n\n- **MCP Native**: Exposes memory tools via JSON-RPC 2.0 over stdio for Claude Code integration\n- **Hybrid Search**: Combines vector similarity (pgvector) with lexical matching (pg_trgm) for optimal recall\n- **Workspace Namespacing**: Project-specific memory isolation via workspace IDs\n- **Entity Extraction**: Optional LLM-based extraction of people, organizations, technologies with knowledge graph\n- **Multi-model Embeddings**: Store embeddings from multiple models simultaneously\n- **TTL Sweeper**: Automatic memory cleanup based on time-to-live settings\n- **Pluggable LLMs**: Supports OpenAI and Google Gemini for embeddings and text normalization\n- **Docker Ready**: Pre-configured Docker Compose with PostgreSQL + pgvector\n- **Single Binary**: Pure Go, no CGO dependencies, compiles to a single static binary\n- **Export/Import**: JSONL format for backup and migration\n\n## Quick Start\n\n### Option 1: Docker (Recommended)\n\nThe easiest way to run Cortex is with Docker Compose, which includes PostgreSQL with pgvector pre-configured.\n\n```bash\n# Clone the repository\ngit clone https://github.com/swiftj/cortex.git\ncd cortex\n\n# Create .env file with your API key\necho \"OPENAI_API_KEY=sk-...\" \u003e .env\n# or for Gemini:\necho \"GEMINI_API_KEY=...\" \u003e .env\necho \"LM_BACKEND=gemini\" \u003e\u003e .env\n\n# Start the services\ndocker-compose up -d\n\n# View logs\ndocker-compose logs -f cortex\n```\n\n#### Using with Claude Code (Docker)\n\nConfigure `.mcp.json` to use the Docker container:\n\n```json\n{\n  \"mcpServers\": {\n    \"cortex\": {\n      \"type\": \"stdio\",\n      \"command\": \"docker-compose\",\n      \"args\": [\"-f\", \"/path/to/cortex/docker-compose.yml\", \"exec\", \"-T\", \"cortex\", \"/usr/local/bin/cortex\"],\n      \"env\": {\n        \"WORKSPACE_ID\": \"my-project\",\n        \"OPENAI_API_KEY\": \"${OPENAI_API_KEY}\"\n      }\n    }\n  }\n}\n```\n\n### Option 2: Manual Installation\n\n#### Prerequisites\n\n- Go 1.24+\n- PostgreSQL 14+ with extensions:\n  - `pgvector` - Vector similarity search\n  - `pg_trgm` - Trigram text similarity\n\n#### Database Setup\n\n```bash\n# Create database\ncreatedb cortex\n\n# Enable required extensions\npsql cortex -c 'CREATE EXTENSION IF NOT EXISTS vector;'\npsql cortex -c 'CREATE EXTENSION IF NOT EXISTS pg_trgm;'\n```\n\n#### Build\n\n```bash\nCGO_ENABLED=0 go build -o bin/cortex ./cmd/mcpserver\n```\n\n#### Configure\n\nSet environment variables:\n\n```bash\n# Required\nexport DATABASE_URL=\"postgres://localhost:5432/cortex?sslmode=disable\"\n\n# Optional (defaults shown)\nexport TENANT_ID=\"local\"\nexport WORKSPACE_ID=\"default\"           # Project-specific isolation\nexport LM_BACKEND=\"openai\"              # or \"gemini\"\nexport LM_MODEL=\"auto\"                  # Chat model for normalization\nexport EMBED_MODEL=\"auto\"               # Single embedding model\nexport EMBED_MODELS=\"\"                  # Comma-separated for multi-model (e.g., \"text-embedding-3-small,text-embedding-3-large\")\nexport SWEEPER_ENABLED=\"true\"           # TTL-based memory cleanup\nexport SWEEPER_INTERVAL=\"1h\"            # Cleanup frequency\nexport ENTITY_EXTRACTION=\"false\"        # LLM-based entity extraction\nexport HEALTH_PORT=\"\"                   # HTTP health endpoint (e.g., \"8080\")\n\n# API Keys (one required based on LM_BACKEND)\nexport OPENAI_API_KEY=\"sk-...\"\n# or\nexport GEMINI_API_KEY=\"...\"\n```\n\n#### Run\n\n```bash\n./bin/cortex\n```\n\nThe server reads JSON-RPC requests from stdin and writes responses to stdout.\n\n## Claude Code Integration\n\nAdd to your `.mcp.json` or Claude Code settings:\n\n```json\n{\n  \"mcpServers\": {\n    \"cortex\": {\n      \"type\": \"stdio\",\n      \"command\": \"/path/to/cortex\",\n      \"env\": {\n        \"DATABASE_URL\": \"postgres://localhost:5432/cortex?sslmode=disable\",\n        \"WORKSPACE_ID\": \"my-project\",\n        \"LM_BACKEND\": \"openai\",\n        \"OPENAI_API_KEY\": \"${OPENAI_API_KEY}\"\n      }\n    }\n  }\n}\n```\n\nRestart Claude Code and the memory tools will be available.\n\n### Per-Project Workspaces\n\nUse `WORKSPACE_ID` to isolate memories per project:\n\n```json\n{\n  \"mcpServers\": {\n    \"cortex\": {\n      \"type\": \"stdio\",\n      \"command\": \"/path/to/cortex\",\n      \"env\": {\n        \"DATABASE_URL\": \"postgres://localhost:5432/cortex?sslmode=disable\",\n        \"WORKSPACE_ID\": \"${PWD##*/}\",\n        \"OPENAI_API_KEY\": \"${OPENAI_API_KEY}\"\n      },\n      \"scope\": [\"${PWD}\"]\n    }\n  }\n}\n```\n\n## Getting Claude Code to Reliably Use Cortex\n\nHaving Cortex installed is only half the battle. The real power comes from Claude Code **proactively** using memory tools during your development sessions. Here are proven strategies to achieve reliable memory usage.\n\n### Strategy 1: Project Instructions (CLAUDE.md)\n\nCreate a `CLAUDE.md` file in your project root with explicit memory directives:\n\n````markdown\n# Project Memory Protocol\n\n## Memory Requirements\nThis project uses Cortex for persistent memory. You MUST:\n\n1. **At session start**: Search memories for project context\n   - `memory.search({ query: \"project architecture decisions\" })`\n   - `memory.search({ query: \"coding standards preferences\" })`\n\n2. **When learning something new**: Store it immediately\n   - User preferences → `memory.add` with kind: \"preference\"\n   - Architecture decisions → `memory.add` with kind: \"fact\", importance: 0.9\n   - Gotchas/pitfalls → `memory.add` with kind: \"note\", tags: [\"gotcha\"]\n\n3. **Before major changes**: Check for relevant context\n   - `memory.search({ query: \"\u003crelevant topic\u003e\" })`\n\n4. **After completing features**: Document learnings\n   - `memory.add({ text: \"Completed X using Y approach\", kind: \"fact\", tags: [\"implementation\"] })`\n````\n\n### Strategy 2: Explicit Prompting Patterns\n\nUse these prompt patterns to trigger memory operations:\n\n**Session Start:**\n\u003e \"Check your memory for any context about this project before we begin.\"\n\n**During Development:**\n\u003e \"Remember that we decided to use X approach for Y.\"\n\u003e \"Store this as an important architectural decision.\"\n\u003e \"What do you remember about how we handle authentication?\"\n\n**Session End:**\n\u003e \"Save the key learnings from this session to memory.\"\n\u003e \"What should we remember for next time?\"\n\n### Strategy 3: Workspace Isolation\n\nConfigure automatic workspace detection in `.mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"cortex\": {\n      \"type\": \"stdio\",\n      \"command\": \"/path/to/cortex\",\n      \"env\": {\n        \"DATABASE_URL\": \"postgres://localhost:5432/cortex?sslmode=disable\",\n        \"WORKSPACE_ID\": \"${PWD##*/}\",\n        \"OPENAI_API_KEY\": \"${OPENAI_API_KEY}\"\n      },\n      \"scope\": [\"${PWD}\"]\n    }\n  }\n}\n```\n\nThis ensures `my-webapp` project memories stay separate from `api-service` memories.\n\n### Strategy 4: Bootstrap Session Pattern\n\nStart each coding session with a bootstrap prompt:\n\n\u003e \"Let's start a development session. First:\n\u003e 1. Search your memory for recent work on this project\n\u003e 2. Search for any user preferences or coding standards\n\u003e 3. Tell me what you remember, then we'll continue\"\n\nThis primes Claude Code to engage with memory from the start.\n\n### Practical Workflow Examples\n\n**Feature Development:**\n```\nYou: \"I want to add user authentication\"\nClaude: *searches memory for auth-related decisions*\nClaude: \"I found we previously decided to use JWT tokens. Let me search for more context...\"\n*implements feature*\nClaude: *stores implementation decisions*\n```\n\n**Bug Investigation:**\n```\nYou: \"There's a bug in the payment flow\"\nClaude: *searches memory for payment-related notes*\nClaude: \"I remember we had a similar issue with currency conversion. Let me check those notes...\"\n```\n\n**Code Review:**\n```\nYou: \"Review this PR\"\nClaude: *searches memory for coding standards and past decisions*\nClaude: \"Based on our established patterns, I notice this doesn't follow our error handling convention...\"\n```\n\n### Memory Categories to Establish\n\nBuild a rich memory foundation with these categories:\n\n| Kind | Use For | Importance |\n|------|---------|------------|\n| `preference` | User coding style, tool preferences | 0.7-0.9 |\n| `fact` | Architecture decisions, API contracts | 0.8-1.0 |\n| `note` | Implementation details, gotchas | 0.5-0.7 |\n| `project` | Project-specific context | 0.6-0.8 |\n| `identity` | Team info, stakeholders | 0.5-0.6 |\n\n### Pro Tips\n\n1. **High-importance memories surface first** - Set `importance: 0.9` for critical decisions\n2. **Use tags consistently** - Tags like `[\"auth\", \"security\"]` help with targeted searches\n3. **Set TTL for temporary context** - Use `ttl_days: 30` for sprint-specific notes\n4. **Review and prune periodically** - Export memories and clean up outdated entries\n5. **Seed initial context** - At project start, manually add key architecture decisions\n\n### Common Pitfalls\n\n| Problem | Solution |\n|---------|----------|\n| Claude doesn't use memory | Add explicit instructions to CLAUDE.md |\n| Too many irrelevant results | Use more specific search queries and tags |\n| Memories getting stale | Enable TTL sweeper, set appropriate `ttl_days` |\n| Cross-project contamination | Ensure `WORKSPACE_ID` is set correctly |\n| Lost context between sessions | Use bootstrap prompts at session start |\n\n## MCP Tools\n\n### `memory.add`\n\nStore a new memory with optional metadata.\n\n```json\n{\n  \"text\": \"User prefers dark mode in all applications\",\n  \"kind\": \"preference\",\n  \"importance\": 0.8,\n  \"tags\": [\"ui\", \"settings\"],\n  \"ttl_days\": 90,\n  \"source\": \"chat\"\n}\n```\n\n**Parameters:**\n- `text` (required): Memory content\n- `kind`: Type (`note`, `fact`, `todo`, `preference`, `identity`, `project`)\n- `importance`: Priority score (0.0 - 1.0, default: 0.5)\n- `tags`: Categorization tags\n- `ttl_days`: Days until auto-expiry\n- `source`: Origin identifier\n\n**Returns**: `{ \"id\": 123 }`\n\n### `memory.search`\n\nSearch memories using hybrid vector + lexical matching.\n\n```json\n{\n  \"query\": \"user interface preferences\",\n  \"k\": 10,\n  \"hybrid\": true,\n  \"model\": \"text-embedding-3-small\"\n}\n```\n\n**Parameters:**\n- `query` (required): Search query\n- `k`: Max results (1-100, default: 10)\n- `hybrid`: Use hybrid search (default: true)\n- `model`: Filter by embedding model (optional)\n\n**Returns**: Array of memories with similarity scores.\n\n### `memory.update`\n\nUpdate an existing memory by ID.\n\n```json\n{\n  \"id\": 123,\n  \"patch\": {\n    \"importance\": 0.9,\n    \"tags\": [\"ui\", \"settings\", \"theme\"]\n  }\n}\n```\n\n### `memory.delete`\n\nRemove a memory by ID.\n\n```json\n{\n  \"id\": 123\n}\n```\n\n### `memory.export`\n\nExport memories to JSONL format.\n\n```json\n{\n  \"include_embeddings\": false,\n  \"kind\": \"preference\",\n  \"limit\": 100\n}\n```\n\n**Returns**: `{ \"data\": \"...\", \"exported\": 100, \"errors\": 0 }`\n\n### `memory.import`\n\nImport memories from JSONL format.\n\n```json\n{\n  \"data\": \"{\\\"id\\\":1,\\\"text\\\":\\\"...\\\",\\\"kind\\\":\\\"note\\\"}\\n{\\\"id\\\":2,...}\",\n  \"skip_existing\": false,\n  \"regenerate_embeddings\": false,\n  \"dry_run\": false\n}\n```\n\n**Returns**: `{ \"total\": 2, \"imported\": 2, \"skipped\": 0, \"errors\": 0 }`\n\n### `memory.entities`\n\nGet entities extracted from a memory (requires `ENTITY_EXTRACTION=true`).\n\n```json\n{\n  \"memory_id\": 123\n}\n```\n\n**Returns**:\n```json\n{\n  \"entities\": [\n    {\"id\": 1, \"name\": \"TypeScript\", \"type\": \"technology\"},\n    {\"id\": 2, \"name\": \"React\", \"type\": \"technology\"}\n  ]\n}\n```\n\n### `memory.related`\n\nFind memories that share entities with a given memory.\n\n```json\n{\n  \"memory_id\": 123,\n  \"k\": 10\n}\n```\n\n**Returns**: Array of related memories with entity overlap scores.\n\n## CLI Mode\n\nCortex supports CLI mode for batch operations:\n\n### Export\n\n```bash\n# Export all memories\n./bin/cortex --export memories.jsonl\n\n# Export with embeddings (larger file)\n./bin/cortex --export memories.jsonl --with-embeddings\n\n# Export specific workspace\nWORKSPACE_ID=my-project ./bin/cortex --export project.jsonl\n```\n\n### Import\n\n```bash\n# Import memories\n./bin/cortex --import memories.jsonl\n\n# Skip existing records\n./bin/cortex --import memories.jsonl --skip-existing\n\n# Regenerate embeddings (requires API key)\n./bin/cortex --import memories.jsonl --regenerate-embeddings\n\n# Dry run (validate without writing)\n./bin/cortex --import memories.jsonl --dry-run\n```\n\n### Re-embed\n\nRe-embed all memories when switching embedding models:\n\n```bash\n# Re-embed with current model\n./bin/cortex --reembed\n\n# Custom batch size and delay (rate limiting)\n./bin/cortex --reembed --reembed-batch-size 50 --reembed-delay 200ms\n\n# Delete old embeddings after re-embedding\n./bin/cortex --reembed --reembed-delete-old\n```\n\n## Architecture\n\n```\ncortex/\n├── cmd/mcpserver/       # Entry point\n├── internal/\n│   ├── db/              # PostgreSQL operations (pgx)\n│   ├── llm/             # LLM adapters (OpenAI, Gemini, MultiEmbedder)\n│   ├── mcp/             # MCP JSON-RPC server\n│   ├── search/          # Hybrid search \u0026 ranking\n│   ├── sweeper/         # TTL-based memory cleanup\n│   ├── entity/          # LLM-based entity extraction\n│   ├── reembed/         # Batch re-embedding utility\n│   └── transfer/        # Export/import (JSONL)\n├── migrations/          # Embedded SQL migrations\n├── docs/                # Documentation\n└── configs/             # Example configurations\n```\n\n### Hybrid Search\n\nCortex combines two search strategies:\n\n1. **Vector Search**: Embeds queries and finds semantically similar memories using cosine distance\n2. **Lexical Search**: Uses PostgreSQL trigram similarity for exact/fuzzy text matching\n\nResults are fused using a weighted combination:\n```\nfinal_score = α × vector_score + (1 - α) × lexical_score\n```\n\nDefault `α = 0.7` (70% vector, 30% lexical).\n\n### Entity Extraction\n\nWhen enabled (`ENTITY_EXTRACTION=true`), Cortex automatically extracts entities from memories:\n\n| Entity Type | Examples |\n|-------------|----------|\n| `person` | Team members, stakeholders |\n| `organization` | Companies, teams |\n| `technology` | Languages, frameworks, tools |\n| `project` | Repositories, products |\n| `concept` | Design patterns, methodologies |\n| `location` | Servers, regions |\n| `event` | Meetings, deadlines |\n\nEntities are linked to memories and can be used to discover related information via `memory.related`.\n\n### LLM Providers\n\n| Provider | Chat Model (default) | Embedding Model (default) | Dimensions |\n|----------|---------------------|---------------------------|------------|\n| OpenAI | gpt-4o-mini | text-embedding-3-small | 1536 |\n| Gemini | gemini-2.0-flash-lite | text-embedding-004 | 768 |\n\n## Database Schema\n\n```sql\n-- Main memories table\nCREATE TABLE memories (\n  id           BIGSERIAL PRIMARY KEY,\n  tenant_id    TEXT NOT NULL DEFAULT 'local',\n  workspace_id TEXT NOT NULL DEFAULT 'default',\n  kind         TEXT NOT NULL,\n  text         TEXT NOT NULL,\n  source       TEXT,\n  created_at   TIMESTAMPTZ DEFAULT now(),\n  updated_at   TIMESTAMPTZ DEFAULT now(),\n  tags         TEXT[] DEFAULT '{}',\n  importance   REAL DEFAULT 0.5,\n  ttl_days     INT,\n  meta         JSONB DEFAULT '{}'\n);\n\n-- Multi-model embeddings (composite primary key)\nCREATE TABLE memory_embeddings (\n  memory_id  BIGINT REFERENCES memories(id) ON DELETE CASCADE,\n  model      TEXT NOT NULL,\n  dims       INT NOT NULL,\n  embedding  VECTOR NOT NULL,\n  PRIMARY KEY (memory_id, model)\n);\n\n-- Entity extraction tables\nCREATE TABLE entities (\n  id           BIGSERIAL PRIMARY KEY,\n  tenant_id    TEXT NOT NULL,\n  workspace_id TEXT NOT NULL,\n  name         TEXT NOT NULL,\n  type         entity_type NOT NULL,\n  aliases      TEXT[] DEFAULT '{}',\n  description  TEXT,\n  meta         JSONB DEFAULT '{}'\n);\n\nCREATE TABLE memory_entities (\n  memory_id  BIGINT REFERENCES memories(id) ON DELETE CASCADE,\n  entity_id  BIGINT REFERENCES entities(id) ON DELETE CASCADE,\n  role       TEXT,\n  confidence REAL DEFAULT 1.0,\n  PRIMARY KEY (memory_id, entity_id)\n);\n\nCREATE TABLE entity_relations (\n  id            BIGSERIAL PRIMARY KEY,\n  source_id     BIGINT REFERENCES entities(id),\n  target_id     BIGINT REFERENCES entities(id),\n  relation_type TEXT NOT NULL\n);\n```\n\n## Configuration Reference\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `DATABASE_URL` | Yes | - | PostgreSQL connection string |\n| `OPENAI_API_KEY` | If OpenAI | - | OpenAI API key |\n| `GEMINI_API_KEY` | If Gemini | - | Google Gemini API key |\n| `TENANT_ID` | No | `local` | Tenant identifier |\n| `WORKSPACE_ID` | No | `default` | Workspace for project isolation |\n| `LM_BACKEND` | No | `openai` | LLM provider (`openai` or `gemini`) |\n| `LM_MODEL` | No | `auto` | Chat model for normalization |\n| `EMBED_MODEL` | No | `auto` | Embedding model |\n| `EMBED_MODELS` | No | - | Comma-separated list for multi-model |\n| `SWEEPER_ENABLED` | No | `true` | Enable TTL cleanup |\n| `SWEEPER_INTERVAL` | No | `1h` | Cleanup frequency |\n| `ENTITY_EXTRACTION` | No | `false` | Enable entity extraction |\n| `HEALTH_PORT` | No | - | HTTP health endpoint port |\n\n## Development\n\n```bash\n# Run tests\ngo test ./...\n\n# Build with optimizations\nCGO_ENABLED=0 go build -trimpath -ldflags \"-s -w\" -o bin/cortex ./cmd/mcpserver\n\n# Check binary size\nls -lh bin/cortex\n```\n\n## Documentation\n\nSee [docs/CLAUDE_CODE_GUIDE.md](docs/CLAUDE_CODE_GUIDE.md) for comprehensive documentation including:\n- Detailed installation guides\n- Configuration options\n- Software development workflows\n- Troubleshooting\n\n## Inspiration\n\nCortex is inspired by [Mem0](https://github.com/mem0ai/mem0), adapted for the MCP ecosystem and Claude Code workflows.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswiftj%2Fcortex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fswiftj%2Fcortex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswiftj%2Fcortex/lists"}