@londer/cortex 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/LICENSE +21 -0
  3. package/README.md +183 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +278 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/config-store.d.ts +15 -0
  9. package/dist/config-store.d.ts.map +1 -0
  10. package/dist/config-store.js +86 -0
  11. package/dist/config-store.js.map +1 -0
  12. package/dist/config.d.ts +28 -0
  13. package/dist/config.d.ts.map +1 -0
  14. package/dist/config.js +39 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/consolidation/cluster-finder.d.ts +5 -0
  17. package/dist/consolidation/cluster-finder.d.ts.map +1 -0
  18. package/dist/consolidation/cluster-finder.js +43 -0
  19. package/dist/consolidation/cluster-finder.js.map +1 -0
  20. package/dist/consolidation/consolidator.d.ts +29 -0
  21. package/dist/consolidation/consolidator.d.ts.map +1 -0
  22. package/dist/consolidation/consolidator.js +296 -0
  23. package/dist/consolidation/consolidator.js.map +1 -0
  24. package/dist/embedding/embedder.d.ts +9 -0
  25. package/dist/embedding/embedder.d.ts.map +1 -0
  26. package/dist/embedding/embedder.js +89 -0
  27. package/dist/embedding/embedder.js.map +1 -0
  28. package/dist/extraction/auto-extractor.d.ts +7 -0
  29. package/dist/extraction/auto-extractor.d.ts.map +1 -0
  30. package/dist/extraction/auto-extractor.js +174 -0
  31. package/dist/extraction/auto-extractor.js.map +1 -0
  32. package/dist/extraction/conversation-buffer.d.ts +15 -0
  33. package/dist/extraction/conversation-buffer.d.ts.map +1 -0
  34. package/dist/extraction/conversation-buffer.js +60 -0
  35. package/dist/extraction/conversation-buffer.js.map +1 -0
  36. package/dist/extraction/extractor.d.ts +23 -0
  37. package/dist/extraction/extractor.d.ts.map +1 -0
  38. package/dist/extraction/extractor.js +108 -0
  39. package/dist/extraction/extractor.js.map +1 -0
  40. package/dist/extraction/tier1-regex.d.ts +7 -0
  41. package/dist/extraction/tier1-regex.d.ts.map +1 -0
  42. package/dist/extraction/tier1-regex.js +119 -0
  43. package/dist/extraction/tier1-regex.js.map +1 -0
  44. package/dist/extraction/tier2-nlp.d.ts +13 -0
  45. package/dist/extraction/tier2-nlp.d.ts.map +1 -0
  46. package/dist/extraction/tier2-nlp.js +195 -0
  47. package/dist/extraction/tier2-nlp.js.map +1 -0
  48. package/dist/extraction/tier3-llm.d.ts +8 -0
  49. package/dist/extraction/tier3-llm.d.ts.map +1 -0
  50. package/dist/extraction/tier3-llm.js +57 -0
  51. package/dist/extraction/tier3-llm.js.map +1 -0
  52. package/dist/index.d.ts +2 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +398 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/llm/anthropic-client.d.ts +18 -0
  57. package/dist/llm/anthropic-client.d.ts.map +1 -0
  58. package/dist/llm/anthropic-client.js +116 -0
  59. package/dist/llm/anthropic-client.js.map +1 -0
  60. package/dist/orchestration/ranker.d.ts +18 -0
  61. package/dist/orchestration/ranker.d.ts.map +1 -0
  62. package/dist/orchestration/ranker.js +124 -0
  63. package/dist/orchestration/ranker.js.map +1 -0
  64. package/dist/orchestration/scope.d.ts +15 -0
  65. package/dist/orchestration/scope.d.ts.map +1 -0
  66. package/dist/orchestration/scope.js +28 -0
  67. package/dist/orchestration/scope.js.map +1 -0
  68. package/dist/storage/neo4j.d.ts +19 -0
  69. package/dist/storage/neo4j.d.ts.map +1 -0
  70. package/dist/storage/neo4j.js +246 -0
  71. package/dist/storage/neo4j.js.map +1 -0
  72. package/dist/storage/qdrant.d.ts +21 -0
  73. package/dist/storage/qdrant.d.ts.map +1 -0
  74. package/dist/storage/qdrant.js +125 -0
  75. package/dist/storage/qdrant.js.map +1 -0
  76. package/dist/storage/sqlite.d.ts +23 -0
  77. package/dist/storage/sqlite.d.ts.map +1 -0
  78. package/dist/storage/sqlite.js +162 -0
  79. package/dist/storage/sqlite.js.map +1 -0
  80. package/dist/templates/claude-instructions.d.ts +11 -0
  81. package/dist/templates/claude-instructions.d.ts.map +1 -0
  82. package/dist/templates/claude-instructions.js +110 -0
  83. package/dist/templates/claude-instructions.js.map +1 -0
  84. package/dist/tools/config.d.ts +21 -0
  85. package/dist/tools/config.d.ts.map +1 -0
  86. package/dist/tools/config.js +96 -0
  87. package/dist/tools/config.js.map +1 -0
  88. package/dist/tools/consolidate.d.ts +4 -0
  89. package/dist/tools/consolidate.d.ts.map +1 -0
  90. package/dist/tools/consolidate.js +16 -0
  91. package/dist/tools/consolidate.js.map +1 -0
  92. package/dist/tools/context.d.ts +8 -0
  93. package/dist/tools/context.d.ts.map +1 -0
  94. package/dist/tools/context.js +84 -0
  95. package/dist/tools/context.js.map +1 -0
  96. package/dist/tools/forget.d.ts +7 -0
  97. package/dist/tools/forget.d.ts.map +1 -0
  98. package/dist/tools/forget.js +49 -0
  99. package/dist/tools/forget.js.map +1 -0
  100. package/dist/tools/graph-query.d.ts +5 -0
  101. package/dist/tools/graph-query.d.ts.map +1 -0
  102. package/dist/tools/graph-query.js +35 -0
  103. package/dist/tools/graph-query.js.map +1 -0
  104. package/dist/tools/ingest.d.ts +8 -0
  105. package/dist/tools/ingest.d.ts.map +1 -0
  106. package/dist/tools/ingest.js +101 -0
  107. package/dist/tools/ingest.js.map +1 -0
  108. package/dist/tools/relate.d.ts +4 -0
  109. package/dist/tools/relate.d.ts.map +1 -0
  110. package/dist/tools/relate.js +10 -0
  111. package/dist/tools/relate.js.map +1 -0
  112. package/dist/tools/search.d.ts +6 -0
  113. package/dist/tools/search.d.ts.map +1 -0
  114. package/dist/tools/search.js +43 -0
  115. package/dist/tools/search.js.map +1 -0
  116. package/dist/tools/store.d.ts +8 -0
  117. package/dist/tools/store.d.ts.map +1 -0
  118. package/dist/tools/store.js +64 -0
  119. package/dist/tools/store.js.map +1 -0
  120. package/dist/types/index.d.ts +289 -0
  121. package/dist/types/index.d.ts.map +1 -0
  122. package/dist/types/index.js +3 -0
  123. package/dist/types/index.js.map +1 -0
  124. package/docker-compose.yml +27 -0
  125. package/package.json +71 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,62 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.2.0] - 2026-03-15
9
+
10
+ ### Added
11
+
12
+ - **Tiered entity extraction** — Three-tier system (Regex → NLP → LLM) with automatic fallback
13
+ - Tier 1: Enhanced regex for snake_case, camelCase, PascalCase, quoted identifiers, and verb-pattern relationships
14
+ - Tier 2: NLP via compromise.js with POS tagging, named entity recognition, and embedding-based dedup
15
+ - Tier 3: Claude API extraction with structured JSON output (requires API key)
16
+ - In-memory LRU cache (SHA-256 key, 5 min TTL, 500 entries)
17
+ - **Automatic memory extraction** — Cortex observes tool calls and proactively extracts knowledge
18
+ - Conversation buffer with configurable size and debounce timer
19
+ - LLM-powered extraction when API key available, local heuristics as fallback
20
+ - Sentence scoring by technical term density, decision words, pattern words
21
+ - Embedding-based dedup against existing memories (threshold > 0.92)
22
+ - **Memory consolidation** — Background process to merge redundant memories
23
+ - Cluster detection via cosine similarity in Qdrant
24
+ - LLM mode: smart merge, contradiction resolution, archival with reasoning
25
+ - Local mode: near-identical dedup (> 0.95), flagging for review (> 0.90)
26
+ - Auto-consolidation timer with configurable interval
27
+ - Audit trail via consolidation_log table
28
+ - **Runtime configuration** — `memory_config` tool for live settings changes
29
+ - View full config with storage status and usage stats
30
+ - Set API key, extraction tier, auto-extract, and consolidation at runtime
31
+ - Persists to `~/.cortex/runtime-config.json`
32
+ - API key masked in responses
33
+ - **New MCP tools**: `memory_ingest`, `memory_consolidate`, `memory_config`
34
+ - **LLM client** — Anthropic API wrapper with retry logic, JSON extraction, token tracking
35
+ - **CLI** (`cortex` command) — serve, setup, init, config, consolidate, version, help
36
+ - **`cortex init`** — generates Claude Code instructions for project or global CLAUDE.md (idempotent, marker-based updates)
37
+ - **npm package** — Published as `@londer/cortex` with proper build step
38
+ - **Conventional commits** — commitlint + husky for commit message enforcement
39
+ - **Build infrastructure** — TypeScript compilation to `dist/`, declaration maps, source maps
40
+
41
+ ### Changed
42
+
43
+ - `memory_store` now auto-extracts entities when not explicitly provided
44
+ - `memory_context` uses tiered extractor instead of basic regex
45
+ - SQLite schema extended with source_type, consolidated_from, extraction_confidence, extraction_tier columns
46
+ - MCP server version bumped to 0.2.0
47
+ - Package renamed to `@londer/cortex`
48
+ - Added `CONTRIBUTING.md` with branching strategy, commit rules, and merge policy
49
+
50
+ ## [0.1.0] - 2026-03-15
51
+
52
+ ### Added
53
+
54
+ - MCP server with stdio transport for Claude Code integration
55
+ - Six core tools: `memory_store`, `memory_search`, `memory_relate`, `memory_graph_query`, `memory_context`, `memory_forget`
56
+ - Triple storage backend: Qdrant (vectors), Neo4j (knowledge graph), SQLite (metadata)
57
+ - Local embedding pipeline using HuggingFace Transformers.js (`all-MiniLM-L6-v2`, 384 dimensions)
58
+ - Tiered memory scoping with automatic project inference and scope boosting
59
+ - Multi-source context retrieval combining semantic search, graph traversal, and recency
60
+ - Orchestration layer with merge, rank, and dedup logic
61
+ - Docker Compose setup for Qdrant and Neo4j
62
+ - Test suite covering all layers: embedding, storage, orchestration, and integration
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Arthur Lonfils / Londer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,183 @@
1
+ # Cortex
2
+
3
+ A high-performance, locally-hosted AI memory system that stores, indexes, and retrieves contextual knowledge via MCP (Model Context Protocol). Designed for Claude Code, but works with any MCP client.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @londer/cortex
9
+ ```
10
+
11
+ Or from source:
12
+
13
+ ```bash
14
+ git clone https://github.com/londer/cortex.git
15
+ cd cortex
16
+ npm install
17
+ npm run build
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ```bash
23
+ # 1. Set up storage backends (Qdrant + Neo4j via Docker)
24
+ cortex setup
25
+
26
+ # 2. Start the MCP server
27
+ cortex serve
28
+ ```
29
+
30
+ ## Claude Code Integration
31
+
32
+ ```bash
33
+ # Add Cortex to Claude Code
34
+ claude mcp add cortex -- cortex serve
35
+
36
+ # Generate Claude Code instructions for your project
37
+ cortex init
38
+
39
+ # Or set up global instructions (applies to all projects)
40
+ cortex init --global
41
+ ```
42
+
43
+ Or manually add to your MCP config:
44
+
45
+ ```json
46
+ {
47
+ "servers": {
48
+ "cortex": {
49
+ "command": "cortex",
50
+ "args": ["serve"]
51
+ }
52
+ }
53
+ }
54
+ ```
55
+
56
+ ## LLM Setup (Optional)
57
+
58
+ Cortex works fully without an API key. Adding one unlocks higher-quality extraction and smart consolidation.
59
+
60
+ ```bash
61
+ # Via CLI
62
+ cortex config set anthropic_api_key sk-ant-your-key-here
63
+
64
+ # Or via environment variable
65
+ export ANTHROPIC_API_KEY=sk-ant-your-key-here
66
+ ```
67
+
68
+ ## Extraction Tiers
69
+
70
+ Cortex uses a tiered entity extraction system:
71
+
72
+ | Tier | Method | Quality | Latency | Cost | Requirements |
73
+ |------|--------|---------|---------|------|-------------|
74
+ | 1 | Regex + Heuristics | Basic | < 1ms | Free | Always available |
75
+ | 2 | NLP (compromise.js) | Good | < 50ms | Free | Always available |
76
+ | 3 | LLM (Claude API) | Best | 500ms-2s | ~$0.002/call | API key required |
77
+
78
+ The system automatically selects the best available tier and falls back gracefully.
79
+
80
+ ## Capability Matrix
81
+
82
+ | Feature | No API Key | With API Key |
83
+ |---------|-----------|-------------|
84
+ | Entity extraction | Tier 1-2 (regex + NLP) | Tier 3 (LLM) |
85
+ | Relationship detection | Basic verb patterns | Full semantic understanding |
86
+ | Auto-extraction | Local heuristics | LLM-powered analysis |
87
+ | Consolidation: near-identical dedup | Yes (> 0.95 similarity) | Yes |
88
+ | Consolidation: smart merge | Flagged for review | Yes |
89
+ | Consolidation: contradiction resolution | No | Yes |
90
+ | memory_ingest | Tier 1-2 extraction | Tier 3 extraction |
91
+ | memory_config | Full access | Full access |
92
+
93
+ ## Available Tools
94
+
95
+ | Tool | Description |
96
+ |------|-------------|
97
+ | `memory_store` | Store a memory. Auto-embeds content, stores metadata, links entities. |
98
+ | `memory_search` | Semantic search with scope boosting. |
99
+ | `memory_relate` | Create entity relationships in the knowledge graph. |
100
+ | `memory_graph_query` | Traverse the knowledge graph from an entity. |
101
+ | `memory_context` | Smart context retrieval combining semantic + graph + recency. |
102
+ | `memory_forget` | Delete a memory from all stores (requires confirmation). |
103
+ | `memory_ingest` | Ingest raw text and extract memories/entities/relationships. |
104
+ | `memory_consolidate` | Merge redundant memories. Supports dry_run preview. |
105
+ | `memory_config` | View/modify runtime configuration (including API key). |
106
+
107
+ ## CLI Reference
108
+
109
+ ```
110
+ cortex serve Start the MCP server (stdio transport)
111
+ cortex setup Pull Docker images, start Qdrant + Neo4j
112
+ cortex setup --stop Stop Docker containers
113
+ cortex init Generate Cortex instructions for project CLAUDE.md
114
+ cortex init --global Generate global instructions (~/.claude/CLAUDE.md)
115
+ cortex config get Show current configuration
116
+ cortex config set <key> <value> Set a runtime config value
117
+ cortex consolidate Run manual consolidation
118
+ cortex version Show version
119
+ cortex help Show help
120
+ ```
121
+
122
+ ## Configuration
123
+
124
+ Configuration is loaded from environment variables with sensible defaults. See `.env.example` for all options.
125
+
126
+ Key settings:
127
+
128
+ | Variable | Default | Description |
129
+ |----------|---------|-------------|
130
+ | `QDRANT_URL` | `http://localhost:16333` | Qdrant server URL |
131
+ | `NEO4J_URI` | `bolt://localhost:17687` | Neo4j bolt URI |
132
+ | `SQLITE_PATH` | `~/.cortex/cortex.db` | SQLite database path |
133
+ | `ANTHROPIC_API_KEY` | *(empty)* | Anthropic API key (optional) |
134
+ | `CORTEX_EXTRACTION_TIER` | `auto` | `auto`, `local-only`, or `llm-preferred` |
135
+ | `CORTEX_AUTO_EXTRACT` | `true` | Enable auto-extraction from conversations |
136
+ | `CORTEX_CONSOLIDATION_ENABLED` | `true` | Enable periodic memory consolidation |
137
+
138
+ Runtime overrides persist to `~/.cortex/runtime-config.json`.
139
+
140
+ ## Development
141
+
142
+ ```bash
143
+ # Run with hot reload
144
+ npm run dev
145
+
146
+ # Run tests (requires Docker backends running)
147
+ npm test
148
+
149
+ # Build
150
+ npm run build
151
+
152
+ # Release (bump version, update changelog, create tag)
153
+ npm run release
154
+ ```
155
+
156
+ ## Architecture
157
+
158
+ ```
159
+ Claude Code
160
+ │ MCP (stdio)
161
+
162
+ ┌──────────────────────────────────────┐
163
+ │ Cortex MCP Server │
164
+ │ (TypeScript) │
165
+ ├──────────────────────────────────────┤
166
+ │ Extraction │ Consolidation │
167
+ │ Tier 1-3 │ LLM / Local │
168
+ │ Auto-extract │ Cluster + Merge │
169
+ ├──────────────────────────────────────┤
170
+ │ Orchestration Layer │
171
+ │ Scope inference, ranking, dedup │
172
+ ├─────────┬──────────┬─────────────────┤
173
+ │ Qdrant │ Neo4j │ SQLite │
174
+ │ vectors │ graph │ metadata │
175
+ └─────────┴──────────┴─────────────────┘
176
+ ▲ ▲
177
+ HuggingFace Anthropic API
178
+ Transformers.js (optional)
179
+ ```
180
+
181
+ ## License
182
+
183
+ MIT - Arthur Lonfils / Londer
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,278 @@
1
+ #!/usr/bin/env node
2
+ import { execSync } from 'node:child_process';
3
+ import { existsSync, mkdirSync, copyFileSync, readFileSync, writeFileSync } from 'node:fs';
4
+ import { join, dirname } from 'node:path';
5
+ import { homedir } from 'node:os';
6
+ import { fileURLToPath } from 'node:url';
7
+ const CORTEX_DIR = join(homedir(), '.cortex');
8
+ const COMPOSE_DEST = join(CORTEX_DIR, 'docker-compose.yml');
9
+ function getVersion() {
10
+ try {
11
+ const __dirname = dirname(fileURLToPath(import.meta.url));
12
+ const pkgPaths = [
13
+ join(__dirname, '..', 'package.json'),
14
+ join(__dirname, '..', '..', 'package.json'),
15
+ ];
16
+ for (const p of pkgPaths) {
17
+ if (existsSync(p)) {
18
+ const pkg = JSON.parse(readFileSync(p, 'utf-8'));
19
+ return pkg.version ?? 'unknown';
20
+ }
21
+ }
22
+ }
23
+ catch { /* fall through */ }
24
+ return 'unknown';
25
+ }
26
+ function printHelp() {
27
+ console.log(`
28
+ cortex — AI memory system with MCP integration
29
+
30
+ Usage:
31
+ cortex serve Start the MCP server (stdio transport)
32
+ cortex setup Pull Docker images and start Qdrant + Neo4j
33
+ cortex setup --stop Stop Docker containers
34
+ cortex init Generate Cortex instructions for project CLAUDE.md
35
+ cortex init --global Generate global Cortex instructions (~/.claude/CLAUDE.md)
36
+ cortex config get Show current configuration
37
+ cortex config set <key> <value> Set a runtime config value
38
+ cortex consolidate Run manual consolidation
39
+ cortex version Show version
40
+ cortex help Show this help message
41
+
42
+ Examples:
43
+ cortex setup Set up storage backends
44
+ cortex serve Start MCP server
45
+ cortex init Add Cortex instructions to current project
46
+ claude mcp add cortex -- cortex serve
47
+ `);
48
+ }
49
+ function checkDocker() {
50
+ try {
51
+ execSync('docker --version', { stdio: 'pipe' });
52
+ return true;
53
+ }
54
+ catch {
55
+ return false;
56
+ }
57
+ }
58
+ function checkDockerCompose() {
59
+ try {
60
+ execSync('docker compose version', { stdio: 'pipe' });
61
+ return 'compose';
62
+ }
63
+ catch {
64
+ try {
65
+ execSync('docker-compose --version', { stdio: 'pipe' });
66
+ return 'docker-compose';
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ }
72
+ }
73
+ async function setup(stop) {
74
+ if (!checkDocker()) {
75
+ console.error('Error: Docker is not installed or not in PATH');
76
+ process.exit(1);
77
+ }
78
+ const composeCmd = checkDockerCompose();
79
+ if (!composeCmd) {
80
+ console.error('Error: Neither "docker compose" nor "docker-compose" is available');
81
+ process.exit(1);
82
+ }
83
+ mkdirSync(CORTEX_DIR, { recursive: true });
84
+ if (!existsSync(COMPOSE_DEST)) {
85
+ const __dirname = dirname(fileURLToPath(import.meta.url));
86
+ const sourcePaths = [
87
+ join(__dirname, '..', 'docker-compose.yml'),
88
+ join(__dirname, '..', '..', 'docker-compose.yml'),
89
+ ];
90
+ let copied = false;
91
+ for (const src of sourcePaths) {
92
+ if (existsSync(src)) {
93
+ copyFileSync(src, COMPOSE_DEST);
94
+ console.log(`Copied docker-compose.yml to ${COMPOSE_DEST}`);
95
+ copied = true;
96
+ break;
97
+ }
98
+ }
99
+ if (!copied) {
100
+ console.error('Warning: Could not find docker-compose.yml to copy');
101
+ }
102
+ }
103
+ const composeArgs = composeCmd === 'compose'
104
+ ? ['docker', 'compose', '-f', COMPOSE_DEST]
105
+ : ['docker-compose', '-f', COMPOSE_DEST];
106
+ if (stop) {
107
+ console.log('Stopping Cortex containers...');
108
+ execSync([...composeArgs, 'down'].join(' '), { stdio: 'inherit' });
109
+ console.log('Containers stopped.');
110
+ return;
111
+ }
112
+ console.log('Starting Cortex containers...');
113
+ execSync([...composeArgs, 'up', '-d'].join(' '), { stdio: 'inherit' });
114
+ console.log('Waiting for services to be ready...');
115
+ const qdrantUrl = process.env.QDRANT_URL ?? 'http://localhost:16333';
116
+ const neo4jUri = process.env.NEO4J_URI ?? 'bolt://localhost:17687';
117
+ let qdrantReady = false;
118
+ for (let i = 0; i < 30; i++) {
119
+ try {
120
+ const resp = await fetch(`${qdrantUrl}/collections`);
121
+ if (resp.ok) {
122
+ qdrantReady = true;
123
+ break;
124
+ }
125
+ }
126
+ catch { /* not ready yet */ }
127
+ await new Promise(r => setTimeout(r, 1000));
128
+ }
129
+ console.log(`Qdrant: ${qdrantReady ? 'ready' : 'not responding (check manually)'}`);
130
+ let neo4jReady = false;
131
+ try {
132
+ const { default: neo4jDriver } = await import('neo4j-driver');
133
+ const driver = neo4jDriver.driver(neo4jUri, neo4jDriver.auth.basic(process.env.NEO4J_USER ?? 'neo4j', process.env.NEO4J_PASSWORD ?? 'cortex-dev'));
134
+ const session = driver.session();
135
+ await session.run('RETURN 1');
136
+ await session.close();
137
+ await driver.close();
138
+ neo4jReady = true;
139
+ }
140
+ catch { /* not ready */ }
141
+ console.log(`Neo4j: ${neo4jReady ? 'ready' : 'not responding (check manually)'}`);
142
+ console.log('\nSetup complete. Run "cortex serve" to start the MCP server.');
143
+ }
144
+ async function configAction(args) {
145
+ const subAction = args[0];
146
+ if (subAction === 'get') {
147
+ const { RuntimeConfigStore } = await import('./config-store.js');
148
+ const { loadConfig } = await import('./config.js');
149
+ const store = new RuntimeConfigStore();
150
+ const baseConfig = loadConfig();
151
+ const overrides = store.getAll();
152
+ console.log('Cortex Configuration:');
153
+ console.log('─'.repeat(40));
154
+ console.log(` Qdrant URL: ${baseConfig.qdrantUrl}`);
155
+ console.log(` Neo4j URI: ${baseConfig.neo4jUri}`);
156
+ console.log(` SQLite Path: ${baseConfig.sqlitePath}`);
157
+ console.log(` Embedding Model: ${baseConfig.embeddingModel}`);
158
+ console.log(` LLM Model: ${baseConfig.llmModel}`);
159
+ console.log(` API Key: ${baseConfig.anthropicApiKey ? 'set' : 'not set'}`);
160
+ console.log(` Extraction Tier: ${baseConfig.extractionTier}`);
161
+ console.log(` Auto-Extract: ${baseConfig.autoExtract}`);
162
+ console.log(` Consolidation: ${baseConfig.consolidationEnabled}`);
163
+ console.log(` Consolidation Int: ${baseConfig.consolidationIntervalMs}ms`);
164
+ if (Object.keys(overrides).length > 0) {
165
+ console.log('\nRuntime Overrides:');
166
+ for (const [key, value] of Object.entries(overrides)) {
167
+ console.log(` ${key}: ${value}`);
168
+ }
169
+ }
170
+ return;
171
+ }
172
+ if (subAction === 'set') {
173
+ const key = args[1];
174
+ const value = args[2];
175
+ if (!key || value === undefined) {
176
+ console.error('Usage: cortex config set <key> <value>');
177
+ process.exit(1);
178
+ }
179
+ const { RuntimeConfigStore } = await import('./config-store.js');
180
+ const store = new RuntimeConfigStore();
181
+ try {
182
+ const result = store.set(key, value);
183
+ console.log(`Set ${key}: ${result.previous ?? '(unset)'} → ${result.current}`);
184
+ }
185
+ catch (error) {
186
+ console.error(`Error: ${error instanceof Error ? error.message : error}`);
187
+ process.exit(1);
188
+ }
189
+ return;
190
+ }
191
+ console.error('Usage: cortex config <get|set>');
192
+ process.exit(1);
193
+ }
194
+ async function initCommand(isGlobal) {
195
+ const { PROJECT_INSTRUCTIONS, GLOBAL_INSTRUCTIONS, START_MARKER, END_MARKER } = await import('./templates/claude-instructions.js');
196
+ if (isGlobal) {
197
+ const claudeDir = join(homedir(), '.claude');
198
+ const targetPath = join(claudeDir, 'CLAUDE.md');
199
+ mkdirSync(claudeDir, { recursive: true });
200
+ writeOrUpdateInstructions(targetPath, GLOBAL_INSTRUCTIONS, START_MARKER, END_MARKER);
201
+ console.log(`Global Cortex instructions written to ${targetPath}`);
202
+ }
203
+ else {
204
+ const targetPath = join(process.cwd(), 'CLAUDE.md');
205
+ writeOrUpdateInstructions(targetPath, PROJECT_INSTRUCTIONS, START_MARKER, END_MARKER);
206
+ console.log(`Cortex instructions written to ${targetPath}`);
207
+ }
208
+ }
209
+ function writeOrUpdateInstructions(filePath, instructions, startMarker, endMarker) {
210
+ if (!existsSync(filePath)) {
211
+ // File doesn't exist — create it with just the instructions
212
+ writeFileSync(filePath, instructions + '\n', 'utf-8');
213
+ return;
214
+ }
215
+ const existing = readFileSync(filePath, 'utf-8');
216
+ const startIdx = existing.indexOf(startMarker);
217
+ const endIdx = existing.indexOf(endMarker);
218
+ if (startIdx !== -1 && endIdx !== -1) {
219
+ // Markers found — replace the section in-place
220
+ const before = existing.slice(0, startIdx);
221
+ const after = existing.slice(endIdx + endMarker.length);
222
+ writeFileSync(filePath, before + instructions + after, 'utf-8');
223
+ }
224
+ else {
225
+ // No markers — append to the file
226
+ const separator = existing.endsWith('\n') ? '\n' : '\n\n';
227
+ writeFileSync(filePath, existing + separator + instructions + '\n', 'utf-8');
228
+ }
229
+ }
230
+ async function serve() {
231
+ await import('./index.js');
232
+ }
233
+ async function consolidate() {
234
+ console.log('Running manual consolidation...');
235
+ console.log('Use the memory_consolidate MCP tool for consolidation.');
236
+ console.log('Example: cortex serve, then call memory_consolidate through Claude Code.');
237
+ }
238
+ async function main() {
239
+ const args = process.argv.slice(2);
240
+ const command = args[0];
241
+ switch (command) {
242
+ case 'serve':
243
+ await serve();
244
+ break;
245
+ case 'setup':
246
+ await setup(args.includes('--stop'));
247
+ break;
248
+ case 'init':
249
+ await initCommand(args.includes('--global'));
250
+ break;
251
+ case 'config':
252
+ await configAction(args.slice(1));
253
+ break;
254
+ case 'consolidate':
255
+ await consolidate();
256
+ break;
257
+ case 'version':
258
+ case '--version':
259
+ case '-v':
260
+ console.log(`cortex v${getVersion()}`);
261
+ break;
262
+ case 'help':
263
+ case '--help':
264
+ case '-h':
265
+ case undefined:
266
+ printHelp();
267
+ break;
268
+ default:
269
+ console.error(`Unknown command: ${command}`);
270
+ printHelp();
271
+ process.exit(1);
272
+ }
273
+ }
274
+ main().catch(error => {
275
+ console.error(`Error: ${error instanceof Error ? error.message : error}`);
276
+ process.exit(1);
277
+ });
278
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export declare class RuntimeConfigStore {
2
+ private overrides;
3
+ constructor();
4
+ get(key: string): string | null;
5
+ getAll(): Record<string, string>;
6
+ getRawApiKey(): string | null;
7
+ set(key: string, value: string): {
8
+ previous: string | null;
9
+ current: string;
10
+ };
11
+ isSettable(key: string): boolean;
12
+ private persist;
13
+ private loadPersisted;
14
+ }
15
+ //# sourceMappingURL=config-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-store.d.ts","sourceRoot":"","sources":["../src/config-store.ts"],"names":[],"mappings":"AAeA,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,SAAS,CAAkC;;IAMnD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAI/B,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAYhC,YAAY,IAAI,MAAM,GAAG,IAAI;IAI7B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG;QAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAa7E,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIhC,OAAO,CAAC,OAAO;IAaf,OAAO,CAAC,aAAa;CActB"}
@@ -0,0 +1,86 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ import { dirname } from 'node:path';
5
+ const CONFIG_DIR = join(homedir(), '.cortex');
6
+ const CONFIG_FILE = join(CONFIG_DIR, 'runtime-config.json');
7
+ const SETTABLE_KEYS = new Set([
8
+ 'anthropic_api_key',
9
+ 'extraction_tier',
10
+ 'auto_extract',
11
+ 'consolidation_enabled',
12
+ ]);
13
+ export class RuntimeConfigStore {
14
+ overrides = new Map();
15
+ constructor() {
16
+ this.loadPersisted();
17
+ }
18
+ get(key) {
19
+ return this.overrides.get(key) ?? null;
20
+ }
21
+ getAll() {
22
+ const result = {};
23
+ for (const [key, value] of this.overrides) {
24
+ if (key === 'anthropic_api_key') {
25
+ result[key] = maskApiKey(value);
26
+ }
27
+ else {
28
+ result[key] = value;
29
+ }
30
+ }
31
+ return result;
32
+ }
33
+ getRawApiKey() {
34
+ return this.overrides.get('anthropic_api_key') ?? null;
35
+ }
36
+ set(key, value) {
37
+ if (!SETTABLE_KEYS.has(key)) {
38
+ throw new Error(`Key "${key}" is not settable at runtime. Settable keys: ${Array.from(SETTABLE_KEYS).join(', ')}`);
39
+ }
40
+ const previous = this.overrides.get(key) ?? null;
41
+ this.overrides.set(key, value);
42
+ this.persist();
43
+ return {
44
+ previous: key === 'anthropic_api_key' && previous ? maskApiKey(previous) : previous,
45
+ current: key === 'anthropic_api_key' ? maskApiKey(value) : value,
46
+ };
47
+ }
48
+ isSettable(key) {
49
+ return SETTABLE_KEYS.has(key);
50
+ }
51
+ persist() {
52
+ try {
53
+ mkdirSync(dirname(CONFIG_FILE), { recursive: true });
54
+ const data = {};
55
+ for (const [key, value] of this.overrides) {
56
+ data[key] = value;
57
+ }
58
+ writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2), 'utf-8');
59
+ }
60
+ catch (error) {
61
+ console.error(`[cortex] Failed to persist runtime config: ${error}`);
62
+ }
63
+ }
64
+ loadPersisted() {
65
+ try {
66
+ if (!existsSync(CONFIG_FILE))
67
+ return;
68
+ const raw = readFileSync(CONFIG_FILE, 'utf-8');
69
+ const data = JSON.parse(raw);
70
+ for (const [key, value] of Object.entries(data)) {
71
+ if (typeof value === 'string') {
72
+ this.overrides.set(key, value);
73
+ }
74
+ }
75
+ }
76
+ catch {
77
+ // No persisted config or invalid file — start fresh
78
+ }
79
+ }
80
+ }
81
+ function maskApiKey(key) {
82
+ if (!key || key.length < 8)
83
+ return '***';
84
+ return key.slice(0, 7) + '...' + key.slice(-4);
85
+ }
86
+ //# sourceMappingURL=config-store.js.map