fleet-mem 0.1.0__tar.gz

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 (65) hide show
  1. fleet_mem-0.1.0/LICENSE +21 -0
  2. fleet_mem-0.1.0/PKG-INFO +580 -0
  3. fleet_mem-0.1.0/README.md +541 -0
  4. fleet_mem-0.1.0/fleet_mem/__init__.py +0 -0
  5. fleet_mem-0.1.0/fleet_mem/__main__.py +5 -0
  6. fleet_mem-0.1.0/fleet_mem/config.py +94 -0
  7. fleet_mem-0.1.0/fleet_mem/embedding/__init__.py +14 -0
  8. fleet_mem-0.1.0/fleet_mem/embedding/base.py +31 -0
  9. fleet_mem-0.1.0/fleet_mem/embedding/cache.py +168 -0
  10. fleet_mem-0.1.0/fleet_mem/embedding/ollama_embed.py +98 -0
  11. fleet_mem-0.1.0/fleet_mem/embedding/openai_compat.py +85 -0
  12. fleet_mem-0.1.0/fleet_mem/fleet/__init__.py +0 -0
  13. fleet_mem-0.1.0/fleet_mem/fleet/branch_index.py +172 -0
  14. fleet_mem-0.1.0/fleet_mem/fleet/cross_agent.py +196 -0
  15. fleet_mem-0.1.0/fleet_mem/fleet/lock_registry.py +171 -0
  16. fleet_mem-0.1.0/fleet_mem/fleet/merge_impact.py +189 -0
  17. fleet_mem-0.1.0/fleet_mem/fleet/stats.py +65 -0
  18. fleet_mem-0.1.0/fleet_mem/indexer.py +267 -0
  19. fleet_mem-0.1.0/fleet_mem/memory/__init__.py +0 -0
  20. fleet_mem-0.1.0/fleet_mem/memory/embedder.py +216 -0
  21. fleet_mem-0.1.0/fleet_mem/memory/engine.py +177 -0
  22. fleet_mem-0.1.0/fleet_mem/observability.py +38 -0
  23. fleet_mem-0.1.0/fleet_mem/server.py +1041 -0
  24. fleet_mem-0.1.0/fleet_mem/splitter/__init__.py +0 -0
  25. fleet_mem-0.1.0/fleet_mem/splitter/ast_splitter.py +365 -0
  26. fleet_mem-0.1.0/fleet_mem/splitter/file_scanner.py +156 -0
  27. fleet_mem-0.1.0/fleet_mem/splitter/text_splitter.py +63 -0
  28. fleet_mem-0.1.0/fleet_mem/sync/__init__.py +4 -0
  29. fleet_mem-0.1.0/fleet_mem/sync/background.py +90 -0
  30. fleet_mem-0.1.0/fleet_mem/sync/merkle.py +163 -0
  31. fleet_mem-0.1.0/fleet_mem/sync/reconciler.py +52 -0
  32. fleet_mem-0.1.0/fleet_mem/sync/synchronizer.py +83 -0
  33. fleet_mem-0.1.0/fleet_mem/sync/watcher.py +155 -0
  34. fleet_mem-0.1.0/fleet_mem/vectordb/__init__.py +7 -0
  35. fleet_mem-0.1.0/fleet_mem/vectordb/base.py +51 -0
  36. fleet_mem-0.1.0/fleet_mem/vectordb/chromadb_store.py +93 -0
  37. fleet_mem-0.1.0/fleet_mem/vectordb/types.py +13 -0
  38. fleet_mem-0.1.0/fleet_mem.egg-info/PKG-INFO +580 -0
  39. fleet_mem-0.1.0/fleet_mem.egg-info/SOURCES.txt +63 -0
  40. fleet_mem-0.1.0/fleet_mem.egg-info/dependency_links.txt +1 -0
  41. fleet_mem-0.1.0/fleet_mem.egg-info/requires.txt +20 -0
  42. fleet_mem-0.1.0/fleet_mem.egg-info/top_level.txt +1 -0
  43. fleet_mem-0.1.0/pyproject.toml +66 -0
  44. fleet_mem-0.1.0/setup.cfg +4 -0
  45. fleet_mem-0.1.0/tests/test_ast_splitter.py +313 -0
  46. fleet_mem-0.1.0/tests/test_async_embedding.py +157 -0
  47. fleet_mem-0.1.0/tests/test_branch_index.py +307 -0
  48. fleet_mem-0.1.0/tests/test_chromadb_store.py +99 -0
  49. fleet_mem-0.1.0/tests/test_config.py +101 -0
  50. fleet_mem-0.1.0/tests/test_cross_agent.py +94 -0
  51. fleet_mem-0.1.0/tests/test_embedding_cache.py +95 -0
  52. fleet_mem-0.1.0/tests/test_file_scanner.py +169 -0
  53. fleet_mem-0.1.0/tests/test_fleet_stats.py +81 -0
  54. fleet_mem-0.1.0/tests/test_index_files.py +242 -0
  55. fleet_mem-0.1.0/tests/test_lock_registry.py +108 -0
  56. fleet_mem-0.1.0/tests/test_memory.py +213 -0
  57. fleet_mem-0.1.0/tests/test_merge_impact.py +160 -0
  58. fleet_mem-0.1.0/tests/test_merkle.py +196 -0
  59. fleet_mem-0.1.0/tests/test_observability.py +30 -0
  60. fleet_mem-0.1.0/tests/test_ollama_embed.py +82 -0
  61. fleet_mem-0.1.0/tests/test_openai_compat.py +103 -0
  62. fleet_mem-0.1.0/tests/test_reconciler.py +110 -0
  63. fleet_mem-0.1.0/tests/test_server.py +571 -0
  64. fleet_mem-0.1.0/tests/test_synchronizer.py +205 -0
  65. fleet_mem-0.1.0/tests/test_watcher.py +117 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-present fleet-mem contributors
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.
@@ -0,0 +1,580 @@
1
+ Metadata-Version: 2.4
2
+ Name: fleet-mem
3
+ Version: 0.1.0
4
+ Summary: Shared code intelligence for agent fleets — AST-aware semantic search + multi-agent memory with git-concurrent coordination
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://github.com/sam-ent/fleet-mem
7
+ Project-URL: Repository, https://github.com/sam-ent/fleet-mem
8
+ Project-URL: Issues, https://github.com/sam-ent/fleet-mem/issues
9
+ Keywords: mcp,agent-memory,code-search,multi-agent,semantic-search,tree-sitter
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Software Development :: Libraries
17
+ Requires-Python: >=3.11
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: mcp>=1.0.0
21
+ Requires-Dist: chromadb>=0.5.0
22
+ Requires-Dist: ollama>=0.3.0
23
+ Requires-Dist: tree-sitter>=0.23.0
24
+ Requires-Dist: tree-sitter-python>=0.23.0
25
+ Requires-Dist: tree-sitter-javascript>=0.23.0
26
+ Requires-Dist: tree-sitter-typescript>=0.23.0
27
+ Requires-Dist: python-dotenv>=1.0.0
28
+ Requires-Dist: xxhash>=3.4.0
29
+ Requires-Dist: watchdog>=4.0.0
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest>=8.0; extra == "dev"
32
+ Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
33
+ Requires-Dist: ruff>=0.4.0; extra == "dev"
34
+ Provides-Extra: languages
35
+ Requires-Dist: tree-sitter-go>=0.23.0; extra == "languages"
36
+ Requires-Dist: tree-sitter-rust>=0.23.0; extra == "languages"
37
+ Requires-Dist: tree-sitter-java>=0.23.0; extra == "languages"
38
+ Dynamic: license-file
39
+
40
+ [![CI](https://github.com/sam-ent/fleet-mem/actions/workflows/ci.yml/badge.svg)](https://github.com/sam-ent/fleet-mem/actions/workflows/ci.yml)
41
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
42
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
43
+ [![MCP](https://img.shields.io/badge/MCP-compatible-green.svg)](https://modelcontextprotocol.io)
44
+
45
+ # fleet-mem
46
+
47
+ Shared code intelligence for agent fleets. AST-aware semantic search, multi-agent memory, and git-concurrent coordination.
48
+
49
+ **When multiple AI agents work on the same codebase, they fight.** Agent A rewrites a function that Agent B is also modifying. Agent C searches for a pattern that Agent D already found and documented. Agents repeat work, create conflicts, and operate on stale information.
50
+
51
+ fleet-mem is a local [MCP](https://modelcontextprotocol.io) server that gives AI coding agents shared context:
52
+
53
+ - **Zero data leakage by default.** Runs entirely on your machine using local Ollama embeddings. No cloud APIs, no telemetry, no data leaves your network. Cloud embedding providers (OpenAI, Gemini, etc.) are available as an opt-in choice.
54
+ - **Token-efficient code search.** Understands the structure of your code via Abstract Syntax Trees (AST). Returns the specific function, not the entire file.
55
+ - **Shared memory across agents.** Agent A discovers "this service uses JWT, not sessions." Agent B finds that knowledge automatically when working on the same code. Memories persist across sessions.
56
+ - **Fleet-aware coordination.** Agents declare what files they are working on, get blocked on conflicts before they start, and get notified when another agent's merge affects their context.
57
+
58
+ ---
59
+
60
+ ## Getting started
61
+
62
+ ### Prerequisites
63
+
64
+ - Python 3.11+
65
+ - [Ollama](https://ollama.ai) running locally (brew, systemd, or Docker)
66
+ - `ollama pull nomic-embed-text`
67
+
68
+ <br>
69
+
70
+ ### Install
71
+
72
+ ```bash
73
+ git clone https://github.com/sam-ent/fleet-mem.git
74
+ cd fleet-mem
75
+ ./scripts/setup.sh # Creates venv, installs deps, registers MCP server
76
+ ```
77
+
78
+ No manual venv activation needed. The MCP client runs fleet-mem using its own venv automatically.
79
+
80
+ <br>
81
+
82
+ ### Docker (alternative)
83
+
84
+ ```bash
85
+ ./scripts/docker-setup.sh
86
+ ```
87
+
88
+ MCP client configuration for Docker:
89
+
90
+ ```json
91
+ {
92
+ "mcpServers": {
93
+ "fleet-mem": {
94
+ "command": "docker",
95
+ "args": ["exec", "-i", "fleet-mem-fleet-mem-1", "python", "-m", "fleet_mem.server"]
96
+ }
97
+ }
98
+ }
99
+ ```
100
+
101
+ Mount your code as a volume to index it:
102
+
103
+ ```yaml
104
+ # Add to docker-compose.yml under fleet-mem.volumes:
105
+ - /path/to/your/projects:/projects:ro
106
+ ```
107
+
108
+ <br>
109
+
110
+ ### Index your codebases
111
+
112
+ ```bash
113
+ ./scripts/index-repos.sh --root ~/projects
114
+ ```
115
+
116
+ <br>
117
+
118
+ ### MCP client configuration
119
+
120
+ Add to your MCP client settings (the `setup.sh` script does this automatically for the default client):
121
+
122
+ ```json
123
+ {
124
+ "mcpServers": {
125
+ "fleet-mem": {
126
+ "command": "/path/to/fleet-mem/.venv/bin/python",
127
+ "args": ["-m", "fleet_mem.server"],
128
+ "cwd": "/path/to/fleet-mem",
129
+ "env": {
130
+ "OLLAMA_HOST": "http://localhost:11434",
131
+ "ANONYMIZED_TELEMETRY": "False"
132
+ }
133
+ }
134
+ }
135
+ }
136
+ ```
137
+
138
+ fleet-mem works with any MCP-compatible client. Your client starts it automatically on the first tool call.
139
+
140
+ <br>
141
+
142
+ ### Example agent queries
143
+
144
+ Once indexed, agents can ask things they could not do with grep:
145
+
146
+ - *"Find the authentication middleware and show me how tokens are validated"*
147
+ - *"Which agent is currently working on the database schema?"*
148
+ - *"What did other agents learn about the payment gateway this session?"*
149
+ - *"If I merge this branch, which agents will have stale context?"*
150
+
151
+ ---
152
+
153
+ ## How it works
154
+
155
+ fleet-mem installs once as a global MCP server. It can index any number of projects. Each project gets its own collection in ChromaDB. All agents share the same server instance.
156
+
157
+ ```
158
+ ~/projects/
159
+ project-a/ indexed as code_project-a
160
+ project-b/ indexed as code_project-b
161
+ project-c/ indexed as code_project-c
162
+
163
+ ~/.local/share/fleet-mem/
164
+ chroma/ vector embeddings (shared)
165
+ memory.db agent memories (shared)
166
+ fleet.db locks, subscriptions (shared)
167
+ ```
168
+
169
+ <br>
170
+
171
+ ### Architecture
172
+
173
+ ```mermaid
174
+ graph LR
175
+ MCP[Any MCP Client] --> FM[fleet-mem]
176
+
177
+ FM --> CS[Code Search]
178
+ FM --> AM[Agent Memory]
179
+ FM --> FC[Fleet Coord]
180
+
181
+ CS --> C[(ChromaDB)]
182
+ CS --> O[Ollama]
183
+ AM --> C
184
+ AM --> M[(memory.db)]
185
+ AM --> O
186
+ FC --> F[(fleet.db)]
187
+ FC --> G[Git]
188
+ ```
189
+
190
+ <br>
191
+
192
+ ### Components
193
+
194
+ | Component | What it is | Why we chose it |
195
+ |-----------|-----------|-----------------|
196
+ | **[Ollama](https://ollama.ai)** | Local ML inference server | Runs embedding models on your machine at zero cost. Supports dozens of models. Works via Docker, systemd, or brew. Swappable via the `Embedding` base class |
197
+ | **[ChromaDB](https://www.trychroma.com/)** | Vector database (HNSW) | Purpose-built for similarity search over embeddings. Runs in-process, no separate server needed |
198
+ | **SQLite + FTS5** | Relational database with full-text search | Agent memories need both keyword search and structured queries. FTS5 + ChromaDB vectors give hybrid ranking via reciprocal rank fusion |
199
+ | **[tree-sitter](https://tree-sitter.github.io/tree-sitter/)** | Incremental parsing library | Splits code into semantic chunks (functions, classes, methods) instead of arbitrary character windows. Search results are meaningful code units, not fragments |
200
+ | **[xxHash](https://xxhash.com) (xxh3_64)** | File change detection + chunk IDs | Detects which files changed between sync cycles. Not a security function, purely for diffing. ~10x faster than SHA-1 |
201
+
202
+ <br>
203
+
204
+ ### Language support
205
+
206
+ | Language | Splitting method | Support level |
207
+ |----------|-----------------|---------------|
208
+ | Python, TypeScript, JavaScript | AST-aware | Tier 1: functions, classes, methods |
209
+ | Go, Rust | AST-aware | Tier 2: functions, types, impl blocks |
210
+ | All other languages | Text-only | Fallback: sliding window (2500 chars, 300 overlap) |
211
+
212
+ AST-aware splitting means search results are complete, meaningful code units. Text-only fallback still works but may return partial functions. Adding a new language requires defining its tree-sitter node types in `src/splitter/ast_splitter.py` (contributions welcome).
213
+
214
+ <br>
215
+
216
+ ### Process flows
217
+
218
+ <br>
219
+
220
+ #### Indexing a codebase
221
+
222
+ > **<ins>Problem</ins>:** Agents read entire files to understand code, burning tokens and missing context across files.
223
+ >
224
+ > **<ins>Solution</ins>:** One-time indexing parses code into semantic chunks and embeds them. Agents search by meaning across the whole codebase.
225
+
226
+ ```mermaid
227
+ sequenceDiagram
228
+ participant S as Setup / Sync
229
+ participant FM as fleet-mem
230
+ participant TS as tree-sitter
231
+ participant OL as Ollama
232
+ participant C as ChromaDB
233
+
234
+ S->>FM: index_codebase(path)
235
+ FM->>FM: Walk files, skip .gitignore
236
+ FM->>TS: Parse into AST
237
+ TS-->>FM: Chunks (functions, classes)
238
+ FM->>OL: Embed (batches of 64)
239
+ OL-->>FM: Vectors
240
+ FM->>C: Upsert chunks + vectors
241
+ FM-->>S: {status: indexed}
242
+ ```
243
+
244
+ <br>
245
+
246
+ #### Semantic code search
247
+
248
+ > **<ins>Problem</ins>:** Grep requires exact strings. Agents don't know file names or function signatures in unfamiliar code.
249
+ >
250
+ > **<ins>Solution</ins>:** Natural language query returns ranked code snippets with file paths and line numbers. No exact match needed.
251
+
252
+ ```mermaid
253
+ sequenceDiagram
254
+ participant A as Agent
255
+ participant FM as fleet-mem
256
+ participant OL as Ollama
257
+ participant C as ChromaDB
258
+
259
+ A->>FM: search_code("auth middleware")
260
+ FM->>OL: Embed query
261
+ OL-->>FM: Query vector
262
+ FM->>C: Nearest-neighbor search
263
+ C-->>FM: Top-K chunks + distances
264
+ FM-->>A: [{file, lines, snippet, score}]
265
+ ```
266
+
267
+ <br>
268
+
269
+ #### Storing and searching memory
270
+
271
+ > **<ins>Problem</ins>:** Agents lose everything they learn when a session ends. The next agent re-discovers the same things from scratch.
272
+ >
273
+ > **<ins>Solution</ins>:** Discoveries persist in a shared memory store. Any agent can find them later via keyword or semantic search.
274
+
275
+ ```mermaid
276
+ sequenceDiagram
277
+ participant A as Agent
278
+ participant FM as fleet-mem
279
+ participant M as memory.db
280
+ participant OL as Ollama
281
+ participant C as ChromaDB
282
+ participant F as fleet.db
283
+
284
+ A->>FM: memory_store("auth uses JWT")
285
+ FM->>M: INSERT memory + FTS index
286
+ FM->>OL: Embed content
287
+ FM->>C: Upsert vector
288
+ FM->>F: Notify matching subscribers
289
+
290
+ A->>FM: memory_search("authentication")
291
+ FM->>M: FTS5 keyword search
292
+ FM->>OL: Embed query
293
+ FM->>C: Vector search
294
+ FM-->>A: Merged ranked results
295
+ ```
296
+
297
+ <br>
298
+
299
+ #### File locking
300
+
301
+ > **<ins>Problem</ins>:** Concurrent agents modify the same files, causing merge conflicts and wasted work.
302
+ >
303
+ > **<ins>Solution</ins>:** Agents declare their work area before starting. Conflicts are caught immediately, not after hours of wasted effort.
304
+
305
+ ```mermaid
306
+ sequenceDiagram
307
+ participant A as Agent A
308
+ participant B as Agent B
309
+ participant FM as fleet-mem
310
+ participant F as fleet.db
311
+
312
+ A->>FM: lock_acquire(["src/auth/*"])
313
+ FM->>F: INSERT lock
314
+ FM-->>A: acquired
315
+
316
+ B->>FM: lock_acquire(["src/auth/login.py"])
317
+ FM->>F: Check overlap (fnmatch)
318
+ FM-->>B: conflict (holder: A)
319
+
320
+ A->>FM: lock_release()
321
+ FM->>F: DELETE lock
322
+
323
+ B->>FM: lock_acquire(["src/auth/login.py"])
324
+ FM-->>B: acquired
325
+ ```
326
+
327
+ <br>
328
+
329
+ #### Cross-agent knowledge sharing
330
+
331
+ > **<ins>Problem</ins>:** Agent A discovers something important about the code. Agent B, working in the same area, has no way to know.
332
+ >
333
+ > **<ins>Solution</ins>:** Agents subscribe to file patterns they care about. When another agent stores a discovery matching that pattern, subscribers are notified automatically.
334
+
335
+ ```mermaid
336
+ sequenceDiagram
337
+ participant A as Agent A
338
+ participant B as Agent B
339
+ participant FM as fleet-mem
340
+ participant F as fleet.db
341
+ participant M as memory.db
342
+ participant C as ChromaDB
343
+
344
+ B->>FM: memory_subscribe(["src/auth/*"])
345
+ FM->>F: INSERT subscription
346
+
347
+ A->>FM: memory_store("auth uses JWT")
348
+ FM->>M: INSERT node
349
+ FM->>C: Embed + store
350
+ FM->>F: Match subscriptions, notify B
351
+
352
+ B->>FM: memory_notifications()
353
+ FM->>F: SELECT unread
354
+ FM-->>B: ["auth uses JWT"]
355
+ ```
356
+
357
+ <br>
358
+
359
+ #### Merge impact preview
360
+
361
+ > **<ins>Problem</ins>:** Agent A merges a PR. Agents B and C are still working on branches that now have stale context. No one tells them.
362
+ >
363
+ > **<ins>Solution</ins>:** Before merging, see exactly which agents, memories, and branches will be affected. After merging, one call notifies everyone and marks stale context.
364
+
365
+ ```mermaid
366
+ sequenceDiagram
367
+ participant AC as Agent / CI
368
+ participant FM as fleet-mem
369
+ participant F as fleet.db
370
+ participant M as memory.db
371
+ participant C as ChromaDB
372
+
373
+ AC->>FM: merge_impact(["src/auth/login.py"])
374
+ FM->>F: Query overlapping locks
375
+ FM->>F: Query matching subscriptions
376
+ FM->>C: Check stale branch overlays
377
+ FM->>M: Query stale file anchors
378
+ FM-->>AC: {locked, subscribed, stale}
379
+
380
+ AC->>FM: notify_merge(branch, files)
381
+ FM->>F: Create notifications
382
+ FM->>M: Mark anchors stale
383
+ ```
384
+
385
+ <br>
386
+
387
+ ### Embedding providers
388
+
389
+ The default is Ollama (local, free). fleet-mem also ships an OpenAI-compatible adapter that works with any provider offering an OpenAI-style embeddings API.
390
+
391
+ | Provider | Setup | Cost |
392
+ |----------|-------|------|
393
+ | **Ollama** (default) | Install Ollama, `ollama pull nomic-embed-text` | Free |
394
+ | **OpenAI** | Set `EMBEDDING_PROVIDER=openai-compat`, `EMBED_API_KEY`, `EMBED_MODEL=text-embedding-3-small` | ~$0.02/1M tokens |
395
+ | **DeepSeek** | Set `EMBED_BASE_URL=https://api.deepseek.com/v1`, `EMBED_API_KEY`, `EMBED_MODEL=deepseek-embed` | ~$0.01/1M tokens |
396
+ | **Gemini** | Set `EMBED_BASE_URL=https://generativelanguage.googleapis.com/v1beta/openai/`, `EMBED_API_KEY`, `EMBED_MODEL=text-embedding-004` | Free tier available |
397
+ | **Together** | Set `EMBED_BASE_URL=https://api.together.xyz/v1`, `EMBED_API_KEY`, model of choice | Varies |
398
+ | **Local vLLM** | Set `EMBED_BASE_URL=http://localhost:8000/v1`, no API key needed | Free |
399
+
400
+ See `.env.example` for full configuration. For providers without an OpenAI-compatible API (Cohere, AWS Bedrock, Hugging Face), see [docs/custom-embedding-providers.md](docs/custom-embedding-providers.md). The adapter interface is four methods and typically under 30 lines.
401
+
402
+ ---
403
+
404
+ ## Features
405
+
406
+ ### Code understanding
407
+
408
+ - **Semantic search**: "find auth middleware" returns relevant functions, not string matches
409
+ - **Symbol lookup**: find function/class definitions across indexed projects
410
+ - **Dependency analysis**: trace what calls or imports a given symbol
411
+ - **Incremental sync**: xxHash Merkle tree detects file changes, re-indexes only deltas
412
+ - **Branch-aware indexing**: overlay collections for feature branches keep changes isolated from the main index
413
+
414
+ <br>
415
+
416
+ ### Fleet coordination
417
+
418
+ - **File lock registry**: agents declare which files they are working on, others check before starting
419
+ - **Cross-agent memory**: agents share discoveries via subscriptions and notifications
420
+ - **Merge impact preview**: before merging, see which in-flight agents would be affected
421
+ - **Post-merge notification**: after merging, automatically notify affected agents and mark stale context
422
+
423
+ ---
424
+
425
+ ## Configuration
426
+
427
+ All settings via environment variables or a `.env` file in the project root. Copy `.env.example` to get started.
428
+
429
+ | Variable | Default | Description |
430
+ |----------|---------|-------------|
431
+ | `OLLAMA_HOST` | `http://localhost:11434` | Ollama API endpoint |
432
+ | `OLLAMA_EMBED_MODEL` | `nomic-embed-text` | Embedding model name |
433
+ | `EMBEDDING_PROVIDER` | `ollama` | Provider: `ollama` or `openai-compat` |
434
+ | `CHROMA_PATH` | `~/.local/share/fleet-mem/chroma` | ChromaDB storage |
435
+ | `MEMORY_DB_PATH` | `~/.local/share/fleet-mem/memory.db` | Agent memory database |
436
+ | `FLEET_DB_PATH` | `~/.local/share/fleet-mem/fleet.db` | Fleet coordination database |
437
+ | `SYNC_INTERVAL` | `300` | Background code index sync (seconds) |
438
+ | `MCP_SETTINGS_FILE` | `~/.claude/settings.json` | MCP client settings path |
439
+
440
+ <br>
441
+
442
+ ### Background sync timing
443
+
444
+ | What | Timing | How |
445
+ |------|--------|-----|
446
+ | **Code index refresh** | Every `SYNC_INTERVAL` seconds (default: 300) | Polls filesystem, computes xxHash digests, re-indexes changed files |
447
+ | **Agent memory writes** | Immediate | Direct SQLite + ChromaDB insert on `memory_store` call |
448
+ | **Lock acquire/release** | Immediate | Direct SQLite write |
449
+ | **Notifications** | Immediate | Created on `memory_store` if subscriptions match |
450
+
451
+ For fast-moving multi-agent work, reduce `SYNC_INTERVAL` to `30`-`60`. File-watching is also available for near-instant sync — set `WATCH_ENABLED=true` to detect changes immediately without polling.
452
+
453
+ <br>
454
+
455
+ ### Scripts
456
+
457
+ | Script | Purpose |
458
+ |--------|---------|
459
+ | `scripts/setup.sh` | One-time install: venv, dependencies, Ollama check, MCP registration |
460
+ | `scripts/index-repos.sh` | Find git repos under a root directory and index each one |
461
+ | `scripts/import-flat-files.py` | Import existing memory files (markdown with YAML frontmatter) |
462
+ | `scripts/embed-existing-nodes.py` | Embed existing memory DB nodes into ChromaDB for semantic search |
463
+
464
+ ---
465
+
466
+ ## Observability
467
+
468
+ fleet-mem includes OpenTelemetry tracing (zero new dependencies, uses the OTel SDK already bundled with ChromaDB). Disabled by default.
469
+
470
+ ### Quick start
471
+
472
+ ```bash
473
+ # Enable tracing and point to your collector
474
+ OTEL_ENABLED=true
475
+ OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 # Jaeger, Grafana Tempo, etc.
476
+ ```
477
+
478
+ ### What is traced
479
+
480
+ | Span | Key attributes |
481
+ |------|---------------|
482
+ | `fleet.index` | project, chunk_count |
483
+ | `fleet.search` | query_hash (never raw query), result_count |
484
+ | `fleet.memory.store` | content_hash, node_type, agent_id |
485
+ | `fleet.memory.search` | query_hash, result_count |
486
+
487
+ All content is hashed in span attributes for privacy. Raw code and queries never appear in traces.
488
+
489
+ ### Fleet stats (no collector needed)
490
+
491
+ The `fleet_stats` MCP tool returns current metrics without requiring an external collector:
492
+
493
+ ```
494
+ fleet_stats() -> {
495
+ collections: {code_myproject: 1523},
496
+ total_chunks: 1523,
497
+ memory_nodes: 47,
498
+ active_locks: 2,
499
+ subscriptions: 5,
500
+ pending_notifications: 1,
501
+ cached_embeddings: 892
502
+ }
503
+ ```
504
+
505
+ ---
506
+
507
+ ## MCP tools reference
508
+
509
+ ### Code search (6 tools)
510
+
511
+ | Tool | Parameters | Description |
512
+ |------|-----------|-------------|
513
+ | `index_codebase` | `path, branch?, force?` | Index a codebase (background). Branch-aware when `branch` specified |
514
+ | `search_code` | `query, path?, branch?, limit?` | Semantic code search across indexed projects |
515
+ | `find_symbol` | `name, file_path?, symbol_type?` | Find symbol definitions (functions, classes) |
516
+ | `find_similar_code` | `code_snippet, limit?` | Find code similar to a given snippet |
517
+ | `get_change_impact` | `file_paths?, symbol_names?` | Find code affected by changes to given files/symbols |
518
+ | `get_dependents` | `symbol_name, depth?` | Trace what calls/imports a symbol (BFS) |
519
+
520
+ <br>
521
+
522
+ ### Agent memory (4 tools)
523
+
524
+ | Tool | Parameters | Description |
525
+ |------|-----------|-------------|
526
+ | `memory_store` | `node_type, content, agent_id?` | Store a memory with optional file anchor |
527
+ | `memory_search` | `query, top_k?, node_type?` | Hybrid keyword + semantic memory search |
528
+ | `memory_promote` | `memory_id, target_scope?` | Promote a project memory to global scope |
529
+ | `stale_check` | `project_path?` | Find memories whose anchored files have changed |
530
+
531
+ <br>
532
+
533
+ ### Fleet coordination (8 tools)
534
+
535
+ | Tool | Parameters | Description |
536
+ |------|-----------|-------------|
537
+ | `lock_acquire` | `agent_id, project, file_patterns` | Declare files an agent is working on |
538
+ | `lock_release` | `agent_id, project` | Release file locks |
539
+ | `lock_query` | `project, file_path?` | Check who holds locks on which files |
540
+ | `merge_impact` | `project, files` | Preview which agents/memories are affected by a merge |
541
+ | `notify_merge` | `project, branch, merged_files` | Post-merge: notify affected agents, mark stale anchors |
542
+ | `memory_feed` | `agent_id?, since_minutes?` | Recent memories from other agents |
543
+ | `memory_subscribe` | `agent_id, file_patterns` | Subscribe to memories about specific files |
544
+ | `memory_notifications` | `agent_id` | Check for new relevant memories from other agents |
545
+
546
+ <br>
547
+
548
+ ### Status and observability (5 tools)
549
+
550
+ | Tool | Parameters | Description |
551
+ |------|-----------|-------------|
552
+ | `get_index_status` | `path` | Check indexing status for a project |
553
+ | `clear_index` | `path` | Drop a project's index and reset |
554
+ | `get_branches` | `path` | List indexed branches with chunk counts |
555
+ | `cleanup_branch` | `path, branch` | Drop a branch overlay after merge |
556
+ | `fleet_stats` | | Current metrics: chunks, memories, locks, cache hits, notifications |
557
+
558
+ ---
559
+
560
+ ## What's next
561
+
562
+ - [ ] Go/Rust recursive AST splitting (promote to Tier 1)
563
+ - [ ] Performance benchmarks on real codebases
564
+ - [ ] MCP client configuration guides for Cursor, Windsurf
565
+ - [ ] Agent workflow templates for common multi-agent patterns
566
+ - [ ] Web dashboard for fleet status visualization
567
+
568
+ See [roadmap.md](roadmap.md) for the full plan.
569
+
570
+ ---
571
+
572
+ ## License
573
+
574
+ MIT
575
+
576
+ <details>
577
+ <summary>Acknowledgments</summary>
578
+
579
+ Architecture inspired by [claude-context](https://github.com/zilliztech/claude-context) by Zilliz (MIT License). Design patterns informed by their TypeScript reference (vector database abstraction, embedding adapter, Merkle DAG, AST splitter). All code is an original Python implementation with significant additions (agent memory, fleet coordination, hybrid search, staleness detection).
580
+ </details>