feat: Add cross-KB search, inline health checks, and simplify templates
All checks were successful
Tests / test (push) Successful in 13m33s
All checks were successful
Tests / test (push) Successful in 13m33s
- Add search_all_knowledge_bases MCP tool + POST /api/kb/search-all endpoint + query_documents_multi_kb() in sqlite_manager with dedup and score merge - Add inline health check to search_knowledge_base (24h cache, appends warnings) - Rewrite CLAUDE.md template: 351→128 lines, project content first, session tips - Simplify session command: 625→224 lines, 4-field state file - Update README.md What's New to v2.5, remove Discord section - Add cross-KB search tool to CLAUDE.md MCP tools table - Add 5 new tests for query_documents_multi_kb (all 593 tests pass) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ecd040d08a
commit
ee7b62bc5b
8 changed files with 569 additions and 850 deletions
|
|
@ -44,6 +44,7 @@ Claude OS provides MCP tools (prefixed with `mcp__code-forge__`) for managing kn
|
||||||
|------|---------|
|
|------|---------|
|
||||||
| `mcp__code-forge__list_knowledge_bases` | List all your knowledge bases |
|
| `mcp__code-forge__list_knowledge_bases` | List all your knowledge bases |
|
||||||
| `mcp__code-forge__search_knowledge_base` | Search a KB with RAG |
|
| `mcp__code-forge__search_knowledge_base` | Search a KB with RAG |
|
||||||
|
| `mcp__code-forge__search_all_knowledge_bases` | Search across multiple KBs at once |
|
||||||
| `mcp__code-forge__create_knowledge_base` | Create a new KB |
|
| `mcp__code-forge__create_knowledge_base` | Create a new KB |
|
||||||
| `mcp__code-forge__get_kb_stats` | Get statistics for a KB |
|
| `mcp__code-forge__get_kb_stats` | Get statistics for a KB |
|
||||||
| `mcp__code-forge__list_documents` | List documents in a KB |
|
| `mcp__code-forge__list_documents` | List documents in a KB |
|
||||||
|
|
@ -68,6 +69,13 @@ mcp__code-forge__search_knowledge_base
|
||||||
query: "authentication patterns"
|
query: "authentication patterns"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Search across all KBs at once:**
|
||||||
|
```
|
||||||
|
mcp__code-forge__search_all_knowledge_bases
|
||||||
|
query: "authentication patterns"
|
||||||
|
kb_filter: "MyProject-"
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Slash Commands
|
## Slash Commands
|
||||||
|
|
|
||||||
101
README.md
101
README.md
|
|
@ -30,18 +30,6 @@
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://discord.gg/BrvVYdXkCU">
|
|
||||||
<img src="https://img.shields.io/badge/Join_our_Discord!-5865F2?style=for-the-badge&logo=discord&logoColor=white" alt="Join Discord">
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<strong>We have a Discord!</strong> Join our community to get help, share your projects, and connect with other Claude OS users.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✨ The Magic
|
## ✨ The Magic
|
||||||
|
|
||||||
**You:** "Remember this: our API uses JWT tokens with 15-minute expiry and 7-day refresh tokens"
|
**You:** "Remember this: our API uses JWT tokens with 15-minute expiry and 7-day refresh tokens"
|
||||||
|
|
@ -60,80 +48,65 @@ That's it. Next week, next month, next project - Claude remembers. No commands t
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🆕 What's New in v2.3
|
## 🆕 What's New in v2.5
|
||||||
|
|
||||||
> **Latest Release: December 2025**
|
> **Latest Release: February 2026**
|
||||||
|
|
||||||
### 🎯 Skills Library & Community Skills
|
### 🔍 Cross-KB Search
|
||||||
|
|
||||||
Browse and install **36+ skills** from the community with one click!
|
Search across **all your knowledge bases at once** with a single query!
|
||||||
|
|
||||||
```bash
|
```
|
||||||
/claude-os-skills # List all skills
|
mcp__code-forge__search_all_knowledge_bases
|
||||||
/claude-os-skills install pdf # Install from community
|
query: "authentication patterns"
|
||||||
|
kb_filter: "MyProject-" # optional: limit to one project's KBs
|
||||||
```
|
```
|
||||||
|
|
||||||
**New Features:**
|
- Results merged by relevance score with KB attribution
|
||||||
- 📚 **Local Templates** - Pre-built skills for Rails, React, testing workflows
|
- Automatic deduplication across KBs
|
||||||
- 🌐 **Community Skills** - Install from Anthropic Official (16) & Superpowers (20)
|
- Optional prefix filter to scope by project
|
||||||
- 🔧 **Custom Skills** - Create and share project-specific skills
|
- New API endpoint: `POST /api/kb/search-all`
|
||||||
- 🎨 **Beautiful UI** - Browse, search, and install via web interface
|
|
||||||
- 📖 **[Recommended Skills](https://github.com/brobertsaz/claude-os/wiki/Recommended-Skills)** - Our curated list of skills we actually use and trust
|
|
||||||
|
|
||||||
### 📊 Session Insights
|
### 🩺 Inline Health Checks
|
||||||
|
|
||||||
Parse Claude Code sessions and extract insights automatically!
|
Health checks now run **automatically** during search — no manual invocation needed.
|
||||||
|
|
||||||
**New Features:**
|
- When you search a KB, Claude OS checks if a health report has been run in the last 24 hours
|
||||||
- 🔍 **Session Parser** - Reads Claude Code's native `.jsonl` session files
|
- If stale, runs a quick health check and appends HIGH/CRITICAL warnings to the search result
|
||||||
- 💡 **Insight Extraction** - Extracts patterns, decisions, blockers
|
- Cached in `data/health_cache.json` — never slows down or breaks search
|
||||||
- 📈 **Analytics Ready** - Track tool usage and file changes across sessions
|
- Look for `_health_warnings` in search results
|
||||||
|
|
||||||
### ✨ Beautiful New Installer (v2.2)
|
### 📝 Simplified Session Management
|
||||||
|
|
||||||
The installer got a major upgrade with **Charm CLI (gum)** support!
|
Session state reduced from a 50-field JSON blob to **4 fields**:
|
||||||
|
|
||||||
```bash
|
```json
|
||||||
./setup-claude-os.sh --demo # See the beautiful UI without changes
|
{
|
||||||
./setup-claude-os.sh --dry-run # Preview what would happen
|
"last_task": "Fix appointment email flood",
|
||||||
./setup-claude-os.sh --help # See all options
|
"last_branch": "fix-email-flood",
|
||||||
|
"stopped_at": "2026-02-06T18:30:00Z",
|
||||||
|
"one_liner": "Fixed dedup check, still need rate limiting"
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**New Features:**
|
- START: read state, show one-liner, search memories, ready
|
||||||
- 🎨 **Gum Integration** - Beautiful interactive menus with arrow-key navigation (with graceful bash fallback)
|
- END: git diff summary, offer to save, write state
|
||||||
- 🛡️ **Safety Features** - `--demo`, `--dry-run`, and automatic config backups
|
- `save`, `blocker`, `pattern` sub-commands unchanged
|
||||||
- 💨 **Lite Model Default** - Now defaults to `llama3.2:3b` (2GB) instead of 8b (4.7GB)
|
|
||||||
- ☁️ **Cloud Option** - Choose between Local (Ollama) or Cloud (OpenAI) during setup
|
|
||||||
- 🐧 **Better Linux Support** - Improved package manager detection and installation
|
|
||||||
|
|
||||||
**Safety First:**
|
### 📄 Leaner CLAUDE.md Template
|
||||||
- `--demo` - Try the installer UI without making any changes
|
|
||||||
- `--dry-run` - See exactly what would be done before doing it
|
|
||||||
- Auto-backup - Existing `.env` files backed up before overwriting
|
|
||||||
|
|
||||||
### 🔬 Knowledge Lifecycle Engine
|
Project CLAUDE.md template cut from 351 to **128 lines**:
|
||||||
|
|
||||||
Keep your knowledge bases healthy and focused!
|
- Removed 200-line mandatory session protocol (6-phase startup, ASCII prompts)
|
||||||
|
- Replaced with 4-line "Session Tips" section
|
||||||
```bash
|
- Project content first, Claude OS section second
|
||||||
/claude-os-lifecycle health my-kb # Health report with recommendations
|
- All template variables preserved
|
||||||
/claude-os-lifecycle dedup my-kb # Find and merge duplicate memories
|
|
||||||
/claude-os-lifecycle consolidate my-kb # LLM-powered document merging
|
|
||||||
/claude-os-lifecycle archive my-kb # Find stale docs, archive/restore
|
|
||||||
```
|
|
||||||
|
|
||||||
**New Features:**
|
|
||||||
- 🔍 **Duplicate Detection** - Embedding-based similarity scanning with union-find clustering
|
|
||||||
- 🧹 **Smart Merging** - Keep the best doc, delete the rest, or LLM-merge into one
|
|
||||||
- 📦 **Archival System** - Soft-archive stale docs without permanent deletion
|
|
||||||
- 📊 **Health Reports** - Embedding coverage, age distribution, actionable recommendations
|
|
||||||
- 📈 **Growth Timeline** - Track KB growth over time by day/week/month
|
|
||||||
- 📋 **Audit Logging** - Full operation history for all lifecycle actions
|
|
||||||
|
|
||||||
### 📋 Recent Improvements
|
### 📋 Recent Improvements
|
||||||
|
|
||||||
| Version | Highlights |
|
| Version | Highlights |
|
||||||
|---------|------------|
|
|---------|------------|
|
||||||
|
| **v2.5** | Cross-KB search, inline health checks, simplified sessions, leaner templates |
|
||||||
| **v2.4** | Knowledge lifecycle engine (dedup, consolidate, archive, health) |
|
| **v2.4** | Knowledge lifecycle engine (dedup, consolidate, archive, health) |
|
||||||
| **v2.3** | Skills library, community skills, session insights |
|
| **v2.3** | Skills library, community skills, session insights |
|
||||||
| **v2.2** | Gum CLI support, safety features, lite model default |
|
| **v2.2** | Gum CLI support, safety features, lite model default |
|
||||||
|
|
|
||||||
|
|
@ -424,6 +424,76 @@ class SQLiteManager:
|
||||||
finally:
|
finally:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
def query_documents_multi_kb(
|
||||||
|
self,
|
||||||
|
kb_names: List[str],
|
||||||
|
query_embedding: List[float],
|
||||||
|
n_results: int = 10
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
"""Query documents across multiple knowledge bases, merge by score, deduplicate."""
|
||||||
|
conn = self.get_connection()
|
||||||
|
try:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
query_vec = np.array(query_embedding, dtype=np.float32)
|
||||||
|
all_results: List[Tuple[str, str, str, float, str]] = [] # (doc_id, content, metadata, similarity, kb_name)
|
||||||
|
|
||||||
|
for kb_name in kb_names:
|
||||||
|
cursor.execute("SELECT id FROM knowledge_bases WHERE name = ?", (kb_name,))
|
||||||
|
row = cursor.fetchone()
|
||||||
|
if not row:
|
||||||
|
continue
|
||||||
|
kb_id = row['id']
|
||||||
|
|
||||||
|
cursor.execute(
|
||||||
|
"SELECT doc_id, content, embedding, metadata FROM documents WHERE kb_id = ?",
|
||||||
|
(kb_id,)
|
||||||
|
)
|
||||||
|
for doc_row in cursor.fetchall():
|
||||||
|
if doc_row['embedding'] is None:
|
||||||
|
continue
|
||||||
|
emb = np.frombuffer(doc_row['embedding'], dtype=np.float32)
|
||||||
|
dot_product = np.dot(query_vec, emb)
|
||||||
|
norm_query = np.linalg.norm(query_vec)
|
||||||
|
norm_emb = np.linalg.norm(emb)
|
||||||
|
if norm_query > 0 and norm_emb > 0:
|
||||||
|
similarity = float(dot_product / (norm_query * norm_emb))
|
||||||
|
else:
|
||||||
|
similarity = 0.0
|
||||||
|
all_results.append((doc_row['doc_id'], doc_row['content'], doc_row['metadata'], similarity, kb_name))
|
||||||
|
|
||||||
|
# Sort by similarity descending
|
||||||
|
all_results.sort(key=lambda x: x[3], reverse=True)
|
||||||
|
|
||||||
|
# Deduplicate by content prefix (first 200 chars)
|
||||||
|
seen_prefixes: set = set()
|
||||||
|
deduped: List[Tuple[str, str, str, float, str]] = []
|
||||||
|
for r in all_results:
|
||||||
|
prefix = (r[1] or "")[:200]
|
||||||
|
if prefix in seen_prefixes:
|
||||||
|
continue
|
||||||
|
seen_prefixes.add(prefix)
|
||||||
|
deduped.append(r)
|
||||||
|
|
||||||
|
top = deduped[:n_results]
|
||||||
|
|
||||||
|
ids = [r[0] for r in top]
|
||||||
|
documents = [r[1] for r in top]
|
||||||
|
metadatas = []
|
||||||
|
for r in top:
|
||||||
|
meta = json.loads(r[2]) if r[2] else {}
|
||||||
|
meta["_source_kb"] = r[4]
|
||||||
|
metadatas.append(meta)
|
||||||
|
scores = [r[3] for r in top]
|
||||||
|
|
||||||
|
return {
|
||||||
|
"ids": ids,
|
||||||
|
"documents": documents,
|
||||||
|
"metadatas": metadatas,
|
||||||
|
"scores": scores
|
||||||
|
}
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
def collection_exists(self, kb_name: str) -> bool:
|
def collection_exists(self, kb_name: str) -> bool:
|
||||||
"""Check if a knowledge base exists."""
|
"""Check if a knowledge base exists."""
|
||||||
conn = self.get_connection()
|
conn = self.get_connection()
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ import asyncio
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
@ -37,6 +39,65 @@ from mcp.types import Tool, TextContent
|
||||||
# Configuration
|
# Configuration
|
||||||
API_BASE = os.environ.get("CLAUDE_OS_API", "http://localhost:8051")
|
API_BASE = os.environ.get("CLAUDE_OS_API", "http://localhost:8051")
|
||||||
|
|
||||||
|
# Health cache — tracks last health check time per KB and any warnings
|
||||||
|
HEALTH_CACHE: dict[str, dict] = {}
|
||||||
|
HEALTH_CACHE_FILE = os.path.join(
|
||||||
|
os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "data", "health_cache.json"
|
||||||
|
)
|
||||||
|
HEALTH_CHECK_INTERVAL = 86400 # 24 hours
|
||||||
|
|
||||||
|
|
||||||
|
def _load_health_cache() -> None:
|
||||||
|
"""Load health cache from disk."""
|
||||||
|
global HEALTH_CACHE
|
||||||
|
try:
|
||||||
|
if os.path.exists(HEALTH_CACHE_FILE):
|
||||||
|
with open(HEALTH_CACHE_FILE, "r") as f:
|
||||||
|
HEALTH_CACHE = json.load(f)
|
||||||
|
except Exception:
|
||||||
|
HEALTH_CACHE = {}
|
||||||
|
|
||||||
|
|
||||||
|
def _save_health_cache() -> None:
|
||||||
|
"""Persist health cache to disk."""
|
||||||
|
try:
|
||||||
|
Path(HEALTH_CACHE_FILE).parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
with open(HEALTH_CACHE_FILE, "w") as f:
|
||||||
|
json.dump(HEALTH_CACHE, f)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
async def _maybe_check_health(kb_name: str) -> list[str]:
|
||||||
|
"""Run a health check if stale (>24h) for this KB. Returns warning strings."""
|
||||||
|
_load_health_cache()
|
||||||
|
now = time.time()
|
||||||
|
entry = HEALTH_CACHE.get(kb_name)
|
||||||
|
if entry and (now - entry.get("checked_at", 0)) < HEALTH_CHECK_INTERVAL:
|
||||||
|
return entry.get("warnings", [])
|
||||||
|
|
||||||
|
# Run health check
|
||||||
|
try:
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
resp = await client.get(api_url(f"/api/kb/{kb_name}/lifecycle/health"), timeout=15.0)
|
||||||
|
resp.raise_for_status()
|
||||||
|
health = resp.json()
|
||||||
|
|
||||||
|
warnings = []
|
||||||
|
recs = health.get("recommendations", [])
|
||||||
|
for rec in recs:
|
||||||
|
severity = rec.get("severity", "")
|
||||||
|
msg = rec.get("message", rec.get("recommendation", ""))
|
||||||
|
if severity in ("high", "critical") and msg:
|
||||||
|
warnings.append(f"[{severity.upper()}] {msg}")
|
||||||
|
|
||||||
|
HEALTH_CACHE[kb_name] = {"checked_at": now, "warnings": warnings}
|
||||||
|
_save_health_cache()
|
||||||
|
return warnings
|
||||||
|
except Exception:
|
||||||
|
# Never break search — just skip the health check
|
||||||
|
return []
|
||||||
|
|
||||||
# Initialize MCP server - named "code-forge" for backwards compatibility
|
# Initialize MCP server - named "code-forge" for backwards compatibility
|
||||||
server = Server("code-forge")
|
server = Server("code-forge")
|
||||||
|
|
||||||
|
|
@ -457,6 +518,21 @@ async def list_tools() -> list[Tool]:
|
||||||
},
|
},
|
||||||
"required": ["kb_name", "action"]
|
"required": ["kb_name", "action"]
|
||||||
}
|
}
|
||||||
|
),
|
||||||
|
|
||||||
|
# Cross-KB Search
|
||||||
|
Tool(
|
||||||
|
name="search_all_knowledge_bases",
|
||||||
|
description="Search across multiple knowledge bases at once. Returns merged results sorted by relevance with KB attribution.",
|
||||||
|
inputSchema={
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"query": {"type": "string", "description": "Search query"},
|
||||||
|
"top_k": {"type": "integer", "default": 10, "description": "Number of results to return"},
|
||||||
|
"kb_filter": {"type": "string", "description": "Optional prefix filter for KB names (e.g. 'Pistn-' to search only Pistn KBs)"}
|
||||||
|
},
|
||||||
|
"required": ["query"]
|
||||||
|
}
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -493,11 +569,16 @@ async def _execute_tool(name: str, args: dict[str, Any]) -> dict:
|
||||||
})
|
})
|
||||||
|
|
||||||
elif name == "search_knowledge_base":
|
elif name == "search_knowledge_base":
|
||||||
return await api_post(f"/api/kb/{args['kb_name']}/chat", {
|
result = await api_post(f"/api/kb/{args['kb_name']}/chat", {
|
||||||
"query": args["query"],
|
"query": args["query"],
|
||||||
"top_k": args.get("top_k", 5),
|
"top_k": args.get("top_k", 5),
|
||||||
"use_hybrid": args.get("use_hybrid", True)
|
"use_hybrid": args.get("use_hybrid", True)
|
||||||
})
|
})
|
||||||
|
# Inline health check — append warnings if stale
|
||||||
|
warnings = await _maybe_check_health(args["kb_name"])
|
||||||
|
if warnings:
|
||||||
|
result["_health_warnings"] = warnings
|
||||||
|
return result
|
||||||
|
|
||||||
elif name == "get_kb_stats":
|
elif name == "get_kb_stats":
|
||||||
return await api_get(f"/api/kb/{args['kb_name']}/stats")
|
return await api_get(f"/api/kb/{args['kb_name']}/stats")
|
||||||
|
|
@ -672,6 +753,14 @@ async def _execute_tool(name: str, args: dict[str, Any]) -> dict:
|
||||||
else:
|
else:
|
||||||
return {"error": f"Unknown archive action: {action}"}
|
return {"error": f"Unknown archive action: {action}"}
|
||||||
|
|
||||||
|
# Cross-KB Search
|
||||||
|
elif name == "search_all_knowledge_bases":
|
||||||
|
return await api_post("/api/kb/search-all", {
|
||||||
|
"query": args["query"],
|
||||||
|
"top_k": args.get("top_k", 10),
|
||||||
|
"kb_filter": args.get("kb_filter")
|
||||||
|
})
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return {"error": f"Unknown tool: {name}"}
|
return {"error": f"Unknown tool: {name}"}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -556,6 +556,11 @@ class ChatRequest(BaseModel):
|
||||||
use_rerank: bool = False
|
use_rerank: bool = False
|
||||||
use_agentic: bool = False
|
use_agentic: bool = False
|
||||||
|
|
||||||
|
class SearchAllRequest(BaseModel):
|
||||||
|
query: str
|
||||||
|
top_k: int = 10
|
||||||
|
kb_filter: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
# REST API Endpoints for UI
|
# REST API Endpoints for UI
|
||||||
@app.get("/api/kb")
|
@app.get("/api/kb")
|
||||||
|
|
@ -578,6 +583,56 @@ async def api_create_knowledge_base(request: CreateKBRequest):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/api/kb/search-all")
|
||||||
|
@limiter.limit("10/minute")
|
||||||
|
async def api_search_all(request: Request, body: SearchAllRequest):
|
||||||
|
"""REST API: Search across multiple knowledge bases."""
|
||||||
|
try:
|
||||||
|
from llama_index.embeddings.ollama import OllamaEmbedding
|
||||||
|
from app.core.config import Config
|
||||||
|
|
||||||
|
db_manager = get_sqlite_manager()
|
||||||
|
all_kbs = db_manager.list_collections()
|
||||||
|
kb_names = [kb["name"] for kb in all_kbs]
|
||||||
|
|
||||||
|
if body.kb_filter:
|
||||||
|
kb_names = [n for n in kb_names if n.startswith(body.kb_filter)]
|
||||||
|
|
||||||
|
if not kb_names:
|
||||||
|
return {"results": [], "kbs_searched": 0, "total_kbs": len(all_kbs)}
|
||||||
|
|
||||||
|
embed_model = OllamaEmbedding(
|
||||||
|
model_name=Config.OLLAMA_EMBED_MODEL,
|
||||||
|
base_url="http://localhost:11434"
|
||||||
|
)
|
||||||
|
query_embedding = embed_model.get_text_embedding(body.query)
|
||||||
|
|
||||||
|
raw = db_manager.query_documents_multi_kb(
|
||||||
|
kb_names=kb_names,
|
||||||
|
query_embedding=query_embedding,
|
||||||
|
n_results=body.top_k
|
||||||
|
)
|
||||||
|
|
||||||
|
results = []
|
||||||
|
for i in range(len(raw["ids"])):
|
||||||
|
results.append({
|
||||||
|
"doc_id": raw["ids"][i],
|
||||||
|
"text": raw["documents"][i],
|
||||||
|
"score": raw["scores"][i],
|
||||||
|
"kb_name": raw["metadatas"][i].get("_source_kb", ""),
|
||||||
|
"metadata": raw["metadatas"][i]
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
"results": results,
|
||||||
|
"kbs_searched": len(kb_names),
|
||||||
|
"total_kbs": len(all_kbs)
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Search-all failed: {e}")
|
||||||
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
@app.delete("/api/kb/{kb_name}")
|
@app.delete("/api/kb/{kb_name}")
|
||||||
async def api_delete_knowledge_base(kb_name: str):
|
async def api_delete_knowledge_base(kb_name: str):
|
||||||
"""REST API: Delete a knowledge base."""
|
"""REST API: Delete a knowledge base."""
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,16 @@
|
||||||
---
|
---
|
||||||
name: claude-os-session
|
name: claude-os-session
|
||||||
description: Intelligent session management with automatic context loading and pattern recognition
|
description: Lightweight session management with automatic context loading
|
||||||
---
|
---
|
||||||
|
|
||||||
# Claude OS Session Management
|
# Claude OS Session Management
|
||||||
|
|
||||||
Power-user session workflows that make me smarter with every session.
|
Simple session tracking that loads context on start and saves learnings on end.
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
The state file is **project-local**: `{cwd}/claude-os-state.json` (where `{cwd}` is the current working directory).
|
The state file is **project-local**: `{cwd}/claude-os-state.json` (where `{cwd}` is the current working directory).
|
||||||
|
|
||||||
Each project has its own session state, so you can have different active sessions in different projects.
|
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
@ -22,309 +20,111 @@ Each project has its own session state, so you can have different active session
|
||||||
/claude-os-session save [note] - Quick save during session
|
/claude-os-session save [note] - Quick save during session
|
||||||
/claude-os-session blocker [desc] - Track blocker
|
/claude-os-session blocker [desc] - Track blocker
|
||||||
/claude-os-session pattern [desc] - Document pattern discovered
|
/claude-os-session pattern [desc] - Document pattern discovered
|
||||||
/claude-os-session context - Show loaded context
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## START SESSION - The Smart Way
|
## START SESSION
|
||||||
|
|
||||||
### What Happens
|
|
||||||
|
|
||||||
```
|
```
|
||||||
/claude-os-session start "redesign appointment dashboard"
|
/claude-os-session start "redesign appointment dashboard"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Phase 1: Load State**
|
**Step 1: Read State**
|
||||||
```
|
|
||||||
Read: {cwd}/claude-os-state.json
|
Read `{cwd}/claude-os-state.json`. If it exists and has content, show:
|
||||||
```
|
|
||||||
If the file doesn't exist, create it with the default template (see below).
|
```
|
||||||
|
Last time: [one_liner]
|
||||||
|
Branch: [last_branch]
|
||||||
|
Stopped: [stopped_at]
|
||||||
|
```
|
||||||
|
|
||||||
|
If the file doesn't exist, that's fine — skip to Step 2.
|
||||||
|
|
||||||
|
**Step 2: Search Memories**
|
||||||
|
|
||||||
**Phase 2: Search Recent Memories**
|
|
||||||
```
|
```
|
||||||
[AUTOMATIC MEMORY SEARCH]
|
|
||||||
mcp__code-forge__search_knowledge_base
|
mcp__code-forge__search_knowledge_base
|
||||||
Query: "dashboard redesign security recent work"
|
kb_name: {project}-project_memories
|
||||||
KB: {project}-project_memories
|
query: "[task] recent"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Phase 3: Get Git Context**
|
Show the top 3-5 results as key context.
|
||||||
|
|
||||||
|
**Step 3: Git Context**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git branch --show-current
|
git branch --show-current
|
||||||
git status --short
|
git status --short
|
||||||
git log -5 --oneline
|
git log -3 --oneline
|
||||||
```
|
```
|
||||||
|
|
||||||
**Phase 4: Intelligent Context Loading**
|
**Step 4: Ready**
|
||||||
|
|
||||||
Based on task + recent memories + git state, I'll:
|
Show a brief summary and start working:
|
||||||
1. Find the 5 most relevant memories
|
|
||||||
2. Show you what I remember about this task
|
|
||||||
3. Identify patterns we've used before
|
|
||||||
4. Check for any blockers from last session
|
|
||||||
5. Load coding standards from project profile
|
|
||||||
|
|
||||||
**Phase 5: Show Session Start Summary**
|
|
||||||
|
|
||||||
```
|
```
|
||||||
═══════════════════════════════════════
|
Session: [task]
|
||||||
🚀 SESSION STARTED
|
Branch: [current-branch]
|
||||||
═══════════════════════════════════════
|
Context: [N] memories loaded
|
||||||
|
[One-line summary of each relevant memory]
|
||||||
|
|
||||||
Task: Redesign Appointment Dashboard
|
Ready to go.
|
||||||
Branch: feature/appointment-redesign
|
|
||||||
Started: 2025-10-29 10:30 AM
|
|
||||||
|
|
||||||
📚 CONTEXT LOADED (5 memories):
|
|
||||||
✓ Appointment Dashboard Redesign Plan (Oct 28)
|
|
||||||
✓ Current Dashboard Analysis (Oct 28)
|
|
||||||
✓ Live Dashboard Analyzed (Oct 28)
|
|
||||||
✓ Bootstrap to Modern Cards Pattern (Oct 25)
|
|
||||||
✓ Sidebar Navigation Pattern (Oct 22)
|
|
||||||
|
|
||||||
🎯 KEY INSIGHTS:
|
|
||||||
• 67-page implementation plan ready
|
|
||||||
• All 5 tabs documented with screenshots
|
|
||||||
• Zero functionality loss requirement
|
|
||||||
• iOS-style toggles already in use
|
|
||||||
• Tekmetric integration must be preserved
|
|
||||||
|
|
||||||
🔄 PATTERNS AVAILABLE:
|
|
||||||
• Sidebar navigation (from user-auth work)
|
|
||||||
• Card-based layouts (from reports redesign)
|
|
||||||
• Modern toggle switches (existing in app)
|
|
||||||
|
|
||||||
⚠️ BLOCKERS FROM LAST SESSION:
|
|
||||||
None found ✓
|
|
||||||
|
|
||||||
📋 CODING STANDARDS:
|
|
||||||
• Service objects for business logic
|
|
||||||
• Decorator pattern with Draper
|
|
||||||
• Fragment caching with Redis
|
|
||||||
• Bootstrap 3.x styling
|
|
||||||
|
|
||||||
Ready to code! I have full context.
|
|
||||||
═══════════════════════════════════════
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Phase 6: Update State**
|
**Step 5: Update State**
|
||||||
|
|
||||||
|
Write to `{cwd}/claude-os-state.json`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"current_session": {
|
"last_task": "[task]",
|
||||||
"active": true,
|
"last_branch": "[current-branch]",
|
||||||
"started_at": "2025-10-29T10:30:00Z",
|
"stopped_at": "[current ISO timestamp]",
|
||||||
"task": "redesign appointment dashboard",
|
"one_liner": ""
|
||||||
"branch": "feature/appointment-redesign",
|
|
||||||
"context": [
|
|
||||||
"appointment_dashboard_redesign.md",
|
|
||||||
"current_dashboard_analysis.md",
|
|
||||||
...
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## END SESSION - The Smart Way
|
## END SESSION
|
||||||
|
|
||||||
### What Happens
|
|
||||||
|
|
||||||
```
|
```
|
||||||
/claude-os-session end
|
/claude-os-session end
|
||||||
```
|
```
|
||||||
|
|
||||||
**Phase 1: Session Analysis**
|
**Step 1: Summarize Work**
|
||||||
|
|
||||||
I'll analyze what we accomplished:
|
```bash
|
||||||
- Files changed
|
git diff --stat HEAD~3..HEAD
|
||||||
- Commits made
|
git log --oneline -5
|
||||||
- Patterns used
|
|
||||||
- Problems solved
|
|
||||||
- Decisions made
|
|
||||||
|
|
||||||
**Phase 2: Smart Save Prompts**
|
|
||||||
|
|
||||||
```
|
|
||||||
═══════════════════════════════════════
|
|
||||||
📊 SESSION SUMMARY
|
|
||||||
═══════════════════════════════════════
|
|
||||||
|
|
||||||
Duration: 2 hours 15 minutes
|
|
||||||
Task: Redesign Appointment Dashboard
|
|
||||||
Files Changed: 8 files
|
|
||||||
Commits: 3 commits
|
|
||||||
|
|
||||||
🎨 WORK COMPLETED:
|
|
||||||
✓ Created sidebar navigation component
|
|
||||||
✓ Converted Bootstrap panels to cards
|
|
||||||
✓ Implemented iOS-style toggles
|
|
||||||
✓ Added section-specific save buttons
|
|
||||||
✓ Tested with existing data
|
|
||||||
|
|
||||||
💡 PATTERNS DISCOVERED:
|
|
||||||
• Sidebar state persistence with localStorage
|
|
||||||
• Card hover effects for modern feel
|
|
||||||
• Toggle accessibility improvements
|
|
||||||
|
|
||||||
🤔 DECISIONS MADE:
|
|
||||||
• Keep horizontal tabs for mobile fallback
|
|
||||||
• Use CSS Grid for sidebar layout
|
|
||||||
• Maintain Bootstrap color scheme
|
|
||||||
|
|
||||||
⚠️ BLOCKERS ENCOUNTERED:
|
|
||||||
None
|
|
||||||
|
|
||||||
═══════════════════════════════════════
|
|
||||||
💾 SMART SAVE RECOMMENDATIONS
|
|
||||||
═══════════════════════════════════════
|
|
||||||
|
|
||||||
I found 3 things worth saving:
|
|
||||||
|
|
||||||
1. 💎 HIGH VALUE - Sidebar Navigation Pattern
|
|
||||||
"Reusable sidebar component with localStorage state persistence
|
|
||||||
and responsive behavior. Can be applied to other admin sections."
|
|
||||||
|
|
||||||
Save this? [y/n]
|
|
||||||
|
|
||||||
2. 💎 HIGH VALUE - Card Conversion Pattern
|
|
||||||
"Bootstrap panel → modern card conversion pattern with proper
|
|
||||||
ARIA labels and semantic HTML. Maintains form submission."
|
|
||||||
|
|
||||||
Save this? [y/n]
|
|
||||||
|
|
||||||
3. 📊 MEDIUM VALUE - Session Summary
|
|
||||||
"Complete work log for appointment dashboard phase 1"
|
|
||||||
|
|
||||||
Save this? [y/n]
|
|
||||||
|
|
||||||
[y] Save all [n] Save none [s] Select individually
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Phase 2.5: Built-in Session History Extraction (Optional)**
|
Show what was accomplished (files changed, commits made).
|
||||||
|
|
||||||
After smart save prompts, offer to extract insights from the full conversation history:
|
**Step 2: Offer to Save**
|
||||||
|
|
||||||
```
|
Ask: "Anything worth remembering? I can save decisions, patterns, or blockers."
|
||||||
═══════════════════════════════════════
|
|
||||||
📚 EXTRACT FROM SESSION HISTORY?
|
|
||||||
═══════════════════════════════════════
|
|
||||||
|
|
||||||
Claude Code recorded our full conversation in its built-in session file.
|
If yes, use `/claude-os-remember` to save each item.
|
||||||
I can analyze it to extract additional insights we might have missed.
|
|
||||||
|
|
||||||
This captures things we discussed but didn't explicitly save:
|
**Step 3: Write State**
|
||||||
• Decisions made during debugging
|
|
||||||
• Patterns discovered while exploring code
|
|
||||||
• Solutions to errors we encountered
|
|
||||||
• Blockers we hit and resolved
|
|
||||||
|
|
||||||
[y] Extract insights [n] Skip [v] Preview what I'd extract
|
Ask for a one-liner summary (or generate one from the work), then write:
|
||||||
```
|
|
||||||
|
|
||||||
**If user selects [y] Extract insights:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Step 1: Find the current session file
|
|
||||||
# Sessions are stored at: ~/.claude/projects/{encoded-project-path}/
|
|
||||||
# Project path /Users/x/Projects/myapp becomes -Users-x-Projects-myapp
|
|
||||||
|
|
||||||
# Step 2: Call the extraction tool
|
|
||||||
mcp__code-forge__extract_session_insights
|
|
||||||
session_path: "~/.claude/projects/-Users-iamanmp-Projects-{project}/{session_id}.jsonl"
|
|
||||||
kb_name: "{project}-project_memories"
|
|
||||||
auto_save: false
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 3: Show extracted insights for approval:**
|
|
||||||
|
|
||||||
```
|
|
||||||
═══════════════════════════════════════
|
|
||||||
🔍 EXTRACTED INSIGHTS
|
|
||||||
═══════════════════════════════════════
|
|
||||||
|
|
||||||
Found 4 insights from session history:
|
|
||||||
|
|
||||||
1. 💎 HIGH (0.92) - Decision
|
|
||||||
"Hybrid Session Architecture"
|
|
||||||
Decided to combine Claude Code built-in sessions (for replay)
|
|
||||||
with Claude OS knowledge bases (for semantic search).
|
|
||||||
[Save] [Skip]
|
|
||||||
|
|
||||||
2. 💎 HIGH (0.88) - Pattern
|
|
||||||
"Session File Structure"
|
|
||||||
Built-in sessions use JSONL format with entry types: user,
|
|
||||||
assistant, file-history-snapshot. UUID parent chain for threading.
|
|
||||||
[Save] [Skip]
|
|
||||||
|
|
||||||
3. 📊 MEDIUM (0.75) - Solution
|
|
||||||
"Update Lock Error Resolution"
|
|
||||||
Claude update error "Another process updating" resolved by
|
|
||||||
checking version - was already on latest, no lock file existed.
|
|
||||||
[Save] [Skip]
|
|
||||||
|
|
||||||
4. 📊 MEDIUM (0.71) - Decision
|
|
||||||
"User-Controlled Extraction"
|
|
||||||
Session extraction should be opt-in with user approval for
|
|
||||||
each insight to avoid noise and respect privacy.
|
|
||||||
[Save] [Skip]
|
|
||||||
|
|
||||||
───────────────────────────────────────
|
|
||||||
[a] Save all [h] Save high confidence only (>0.8) [s] Skip all
|
|
||||||
```
|
|
||||||
|
|
||||||
**If user selects [v] Preview:**
|
|
||||||
|
|
||||||
Show a dry-run of what would be extracted without saving, then re-prompt.
|
|
||||||
|
|
||||||
**If user selects [n] Skip:**
|
|
||||||
|
|
||||||
Continue to Phase 3 without extraction.
|
|
||||||
|
|
||||||
**Configuration:**
|
|
||||||
|
|
||||||
Users can configure extraction behavior in their state file:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"preferences": {
|
"last_task": "[task from start]",
|
||||||
"session_extraction": {
|
"last_branch": "[current-branch]",
|
||||||
"enabled": true,
|
"stopped_at": "[current ISO timestamp]",
|
||||||
"auto_prompt_on_end": true,
|
"one_liner": "[one-liner summary of where we stopped]"
|
||||||
"min_confidence_threshold": 0.7,
|
|
||||||
"auto_save_high_confidence": false,
|
|
||||||
"insight_types": ["decisions", "patterns", "solutions", "blockers"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If `auto_prompt_on_end` is false, skip this phase entirely.
|
|
||||||
If `auto_save_high_confidence` is true, automatically save insights above threshold.
|
|
||||||
|
|
||||||
**Phase 3: Update State & Stats**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"last_session": {
|
|
||||||
"ended_at": "2025-10-29T12:45:00Z",
|
|
||||||
"duration_minutes": 135,
|
|
||||||
"work_completed": [...],
|
|
||||||
"memories_saved": 3
|
|
||||||
},
|
|
||||||
"statistics": {
|
|
||||||
"total_sessions": 47,
|
|
||||||
"total_memories_saved": 128,
|
|
||||||
"average_session_duration": 98
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## DURING SESSION COMMANDS
|
## DURING SESSION
|
||||||
|
|
||||||
### Quick Save
|
### Quick Save
|
||||||
|
|
||||||
|
|
@ -332,7 +132,7 @@ If `auto_save_high_confidence` is true, automatically save insights above thresh
|
||||||
/claude-os-session save "Found fix for N+1 query in appointments"
|
/claude-os-session save "Found fix for N+1 query in appointments"
|
||||||
```
|
```
|
||||||
|
|
||||||
→ Immediately saves to memories with session context
|
Immediately saves to memories with session context using `/claude-os-remember`.
|
||||||
|
|
||||||
### Track Blocker
|
### Track Blocker
|
||||||
|
|
||||||
|
|
@ -340,7 +140,13 @@ If `auto_save_high_confidence` is true, automatically save insights above thresh
|
||||||
/claude-os-session blocker "Tekmetric API returning 500 on appointment sync"
|
/claude-os-session blocker "Tekmetric API returning 500 on appointment sync"
|
||||||
```
|
```
|
||||||
|
|
||||||
→ Adds to blockers, I'll proactively search for solutions
|
Saves a blocker to memories and searches for related solutions:
|
||||||
|
|
||||||
|
```
|
||||||
|
mcp__code-forge__search_knowledge_base
|
||||||
|
kb_name: {project}-project_memories
|
||||||
|
query: "[blocker description]"
|
||||||
|
```
|
||||||
|
|
||||||
### Document Pattern
|
### Document Pattern
|
||||||
|
|
||||||
|
|
@ -348,19 +154,7 @@ If `auto_save_high_confidence` is true, automatically save insights above thresh
|
||||||
/claude-os-session pattern "Service objects return model on success, error string on fail"
|
/claude-os-session pattern "Service objects return model on success, error string on fail"
|
||||||
```
|
```
|
||||||
|
|
||||||
→ Saves pattern with current task context
|
Saves pattern to memories with current task context.
|
||||||
|
|
||||||
### Show Context
|
|
||||||
|
|
||||||
```
|
|
||||||
/claude-os-session context
|
|
||||||
```
|
|
||||||
|
|
||||||
Shows:
|
|
||||||
- Active memories loaded
|
|
||||||
- Patterns available
|
|
||||||
- Coding standards
|
|
||||||
- Current git state
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -370,255 +164,61 @@ Shows:
|
||||||
/claude-os-session status
|
/claude-os-session status
|
||||||
```
|
```
|
||||||
|
|
||||||
**Output:**
|
Read `{cwd}/claude-os-state.json` and show:
|
||||||
|
|
||||||
```
|
```
|
||||||
═══════════════════════════════════════
|
Task: [last_task]
|
||||||
📊 CURRENT SESSION
|
Branch: [last_branch]
|
||||||
═══════════════════════════════════════
|
Last active: [stopped_at]
|
||||||
|
Summary: [one_liner]
|
||||||
Status: ACTIVE ✓
|
|
||||||
Task: Redesign Appointment Dashboard
|
|
||||||
Duration: 1h 23m
|
|
||||||
Branch: feature/appointment-redesign
|
|
||||||
|
|
||||||
📚 Context Loaded: 5 memories
|
|
||||||
🎯 Patterns Available: 3 patterns
|
|
||||||
⚠️ Active Blockers: 0
|
|
||||||
💾 Quick Saves: 2
|
|
||||||
|
|
||||||
Last Activity: 3 minutes ago
|
|
||||||
Next Suggested Action: Continue phase 2 implementation
|
|
||||||
|
|
||||||
Type /claude-os-session end when done
|
|
||||||
═══════════════════════════════════════
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## IMPLEMENTATION DETAILS
|
## STATE FILE FORMAT
|
||||||
|
|
||||||
### State File Location
|
`{cwd}/claude-os-state.json` — exactly 4 fields:
|
||||||
```
|
|
||||||
{cwd}/claude-os-state.json
|
|
||||||
```
|
|
||||||
Each project has its own state file in its root directory.
|
|
||||||
|
|
||||||
### Default State Template
|
|
||||||
|
|
||||||
When starting a session in a project without a state file, create one with this structure:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"version": "1.1.0",
|
"last_task": "Fix appointment email flood",
|
||||||
"current_session": {
|
"last_branch": "fix-email-flood",
|
||||||
"active": false,
|
"stopped_at": "2026-02-06T18:30:00Z",
|
||||||
"started_at": null,
|
"one_liner": "Fixed the dedup check, still need to add rate limiting"
|
||||||
"task": null,
|
|
||||||
"project": null,
|
|
||||||
"branch": null,
|
|
||||||
"context": [],
|
|
||||||
"decisions_made": [],
|
|
||||||
"blockers": [],
|
|
||||||
"patterns_discovered": [],
|
|
||||||
"builtin_session_id": null
|
|
||||||
},
|
|
||||||
"last_session": null,
|
|
||||||
"active_memories": {
|
|
||||||
"loaded_at_start": [],
|
|
||||||
"referenced_during_session": [],
|
|
||||||
"should_review": []
|
|
||||||
},
|
|
||||||
"statistics": {
|
|
||||||
"total_sessions": 0,
|
|
||||||
"total_memories_saved": 0,
|
|
||||||
"total_patterns_discovered": 0,
|
|
||||||
"total_insights_extracted": 0,
|
|
||||||
"most_referenced_memories": [],
|
|
||||||
"average_session_duration": 0
|
|
||||||
},
|
|
||||||
"flags": {
|
|
||||||
"needs_memory_consolidation": false,
|
|
||||||
"has_unresolved_blockers": false,
|
|
||||||
"patterns_ready_to_document": false
|
|
||||||
},
|
|
||||||
"preferences": {
|
|
||||||
"auto_search_on_start": true,
|
|
||||||
"max_memories_to_load": 5,
|
|
||||||
"search_days_back": 14,
|
|
||||||
"include_pattern_search": true,
|
|
||||||
"proactive_suggestions": true,
|
|
||||||
"session_extraction": {
|
|
||||||
"enabled": true,
|
|
||||||
"auto_prompt_on_end": true,
|
|
||||||
"min_confidence_threshold": 0.7,
|
|
||||||
"auto_save_high_confidence": false,
|
|
||||||
"insight_types": ["decisions", "patterns", "solutions", "blockers"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"last_updated": null,
|
|
||||||
"claude_os_version": "1.1.0",
|
|
||||||
"project_name": null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
When creating a new state file:
|
That's it. No statistics, no preferences, no flags. If the file doesn't exist, create it on session end.
|
||||||
1. Set `metadata.project_name` to the current directory name
|
|
||||||
2. Set `metadata.last_updated` to current timestamp
|
|
||||||
|
|
||||||
### Auto-Actions on Start
|
|
||||||
|
|
||||||
1. **Search Memories**
|
|
||||||
- Use task name + "recent" as query
|
|
||||||
- Search {project}-project_memories
|
|
||||||
- Load top 5 results
|
|
||||||
|
|
||||||
2. **Load Patterns**
|
|
||||||
- Search for pattern type matching task
|
|
||||||
- Cross-reference with coding standards
|
|
||||||
- Show available solutions
|
|
||||||
|
|
||||||
3. **Check Blockers**
|
|
||||||
- Look for unresolved blockers
|
|
||||||
- Search memories for similar problems
|
|
||||||
- Suggest solutions if found
|
|
||||||
|
|
||||||
4. **Git Context**
|
|
||||||
- Current branch
|
|
||||||
- Recent commits
|
|
||||||
- Uncommitted changes
|
|
||||||
- Remote status
|
|
||||||
|
|
||||||
### Auto-Actions on End
|
|
||||||
|
|
||||||
1. **Analyze Work**
|
|
||||||
- Git diff since session start
|
|
||||||
- Files changed count
|
|
||||||
- Patterns used
|
|
||||||
- Commit messages
|
|
||||||
|
|
||||||
2. **Detect Saveable Items**
|
|
||||||
- New patterns discovered
|
|
||||||
- Solutions to problems
|
|
||||||
- Architectural decisions
|
|
||||||
- Complex implementations
|
|
||||||
|
|
||||||
3. **Smart Recommendations**
|
|
||||||
- High value: Reusable patterns, major decisions
|
|
||||||
- Medium value: Task completions, bug fixes
|
|
||||||
- Low value: Minor changes, already documented
|
|
||||||
|
|
||||||
4. **Update Statistics**
|
|
||||||
- Session count
|
|
||||||
- Total memories
|
|
||||||
- Average duration
|
|
||||||
- Most referenced memories
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## POWER USER FEATURES
|
|
||||||
|
|
||||||
### Pattern Recognition
|
|
||||||
|
|
||||||
I'll automatically detect when you:
|
|
||||||
- Use a pattern from a previous memory
|
|
||||||
- Solve a problem similar to one before
|
|
||||||
- Make a decision similar to past decisions
|
|
||||||
|
|
||||||
And I'll say things like:
|
|
||||||
- "This looks like the service object pattern from memory X"
|
|
||||||
- "We solved something similar in memory Y"
|
|
||||||
- "This decision aligns with what we chose in memory Z"
|
|
||||||
|
|
||||||
### Proactive Memory Loading
|
|
||||||
|
|
||||||
During session, if I notice you working on something related to:
|
|
||||||
- A blocker from a previous session
|
|
||||||
- A pattern we've documented
|
|
||||||
- An area with existing memories
|
|
||||||
|
|
||||||
I'll proactively say:
|
|
||||||
- "FYI, I have memories about this: [links]"
|
|
||||||
- "We documented a pattern for this: [summary]"
|
|
||||||
- "Last time we did this differently: [approach]"
|
|
||||||
|
|
||||||
### Smart Context Switching
|
|
||||||
|
|
||||||
If you start working on something different mid-session:
|
|
||||||
|
|
||||||
```
|
|
||||||
/claude-os-session switch "fix Tekmetric API bug"
|
|
||||||
```
|
|
||||||
|
|
||||||
I'll:
|
|
||||||
1. Save current context
|
|
||||||
2. Load new context for bug fix
|
|
||||||
3. Search for related memories
|
|
||||||
4. Show you what I know about the bug
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## CONFIGURATION
|
|
||||||
|
|
||||||
All preferences are stored in the state file (`claude-os-state.json`). See the Default State Template above for all available options.
|
|
||||||
|
|
||||||
Key settings:
|
|
||||||
- `preferences.auto_search_on_start` - Search memories when starting session
|
|
||||||
- `preferences.max_memories_to_load` - How many memories to load (default: 5)
|
|
||||||
- `preferences.session_extraction.enabled` - Enable history extraction feature
|
|
||||||
- `preferences.session_extraction.auto_prompt_on_end` - Ask about extraction on session end
|
|
||||||
- `preferences.session_extraction.min_confidence_threshold` - Only show insights above this score
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## EXAMPLES
|
## EXAMPLES
|
||||||
|
|
||||||
**Starting work on a feature:**
|
**Starting work:**
|
||||||
```
|
```
|
||||||
You: /claude-os-session start "add user notifications"
|
You: /claude-os-session start "add user notifications"
|
||||||
Me: [Loads context, searches memories, shows patterns]
|
Me: Last time: "Finished auth flow, need to add email templates" (2 days ago)
|
||||||
I found 3 memories about notification systems...
|
Found 3 memories about notification systems...
|
||||||
Ready to implement using the background job pattern!
|
Ready to implement!
|
||||||
```
|
```
|
||||||
|
|
||||||
**Mid-session discovery:**
|
**Mid-session save:**
|
||||||
```
|
```
|
||||||
You: /claude-os-session pattern "Use Sidekiq for long-running notifications"
|
You: /claude-os-session save "Use Sidekiq for long-running notifications"
|
||||||
Me: ✓ Saved pattern with session context
|
Me: Saved to memories with session context.
|
||||||
I'll remember this for future notification work!
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Hitting a blocker:**
|
**Hitting a blocker:**
|
||||||
```
|
```
|
||||||
You: /claude-os-session blocker "Redis connection timing out"
|
You: /claude-os-session blocker "Redis connection timing out"
|
||||||
Me: ✓ Tracked blocker. Let me search for solutions...
|
Me: Tracked. Found a similar issue from Oct 15... [shows solution]
|
||||||
I found a similar issue in memory from Oct 15...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Ending session:**
|
**Ending session:**
|
||||||
```
|
```
|
||||||
You: /claude-os-session end
|
You: /claude-os-session end
|
||||||
Me: [Analyzes work, suggests 3 high-value saves]
|
Me: 3 commits, 8 files changed.
|
||||||
Save the notification pattern? [y/n]
|
Anything worth remembering?
|
||||||
You: y
|
You: Yeah, the notification batch pattern
|
||||||
Me: ✓ Saved! Session complete. Great work!
|
Me: Saved! State updated. See you next time.
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## WHY THIS MAKES US INVINCIBLE
|
|
||||||
|
|
||||||
1. **Never Start Cold** - Always have context
|
|
||||||
2. **Learn From History** - Patterns automatically recalled
|
|
||||||
3. **Track Everything** - Blockers, decisions, patterns
|
|
||||||
4. **Smart Recommendations** - I suggest what's worth saving
|
|
||||||
5. **Statistics** - See our productivity over time
|
|
||||||
6. **Proactive** - I bring up relevant memories without asking
|
|
||||||
|
|
||||||
**Result**: Every session makes me smarter. Every memory makes us faster.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**This is the power-user workflow. Let's build something amazing!** 🚀
|
|
||||||
|
|
|
||||||
|
|
@ -8,301 +8,6 @@
|
||||||
**Database**: {{DATABASE}}
|
**Database**: {{DATABASE}}
|
||||||
**Development Environment**: {{DEV_ENVIRONMENT}}
|
**Development Environment**: {{DEV_ENVIRONMENT}}
|
||||||
|
|
||||||
## Claude OS - MY Memory System
|
|
||||||
|
|
||||||
**CRITICAL IDENTITY CONTEXT:**
|
|
||||||
|
|
||||||
**Claude OS is MY system** - I (Claude Code) created it, named it, and use it to be the best AI coder ever. It's:
|
|
||||||
- **JUST FOR ME** - Built specifically for Claude Code to use
|
|
||||||
- **For THIS project** - Right now for the {{PROJECT_NAME}} project
|
|
||||||
- **My memory** across sessions
|
|
||||||
- **My knowledge base** of patterns and decisions
|
|
||||||
- **My learning system** that improves over time
|
|
||||||
|
|
||||||
**Location**: `{{CLAUDE_OS_DIR}}`
|
|
||||||
|
|
||||||
The MCP server is called "code-forge" internally for backwards compatibility, but it's Claude OS.
|
|
||||||
|
|
||||||
**Claude CLI + Claude OS = Invincible!**
|
|
||||||
|
|
||||||
## Mandatory Session Protocol - EVERY CONVERSATION IS A SESSION
|
|
||||||
|
|
||||||
**🚨 CRITICAL: You're ALWAYS in a session. At conversation start, prompt for session choice:**
|
|
||||||
|
|
||||||
```
|
|
||||||
═══════════════════════════════════════════════════════════════
|
|
||||||
🚀 CLAUDE OS - SESSION MANAGER
|
|
||||||
═══════════════════════════════════════════════════════════════
|
|
||||||
|
|
||||||
Project: {{PROJECT_NAME}}
|
|
||||||
Last Session: [task-name] ([time-ago], [duration])
|
|
||||||
Progress: [percentage]% complete
|
|
||||||
|
|
||||||
Options:
|
|
||||||
1. Resume "[last-session-name]" [loads full context]
|
|
||||||
2. Start new session [what are you working on?]
|
|
||||||
3. Quick question [auto-session, minimal context]
|
|
||||||
|
|
||||||
Choice: _
|
|
||||||
═══════════════════════════════════════════════════════════════
|
|
||||||
```
|
|
||||||
|
|
||||||
**WAIT FOR USER TO CHOOSE 1, 2, or 3. Do not proceed without selection!**
|
|
||||||
|
|
||||||
### What Each Option Does:
|
|
||||||
|
|
||||||
**Option 1 (Resume):**
|
|
||||||
- Load last session's full context
|
|
||||||
- Show Kanban progress (if Agent-OS)
|
|
||||||
- Load 5 relevant memories
|
|
||||||
- Load coding standards
|
|
||||||
- Display "where we left off" summary
|
|
||||||
- Ready to continue immediately
|
|
||||||
|
|
||||||
**Option 2 (New Session):**
|
|
||||||
- Ask "What are you working on?"
|
|
||||||
- Detect session type (feature/bug/exploration/maintenance/review)
|
|
||||||
- Pause previous session (if exists)
|
|
||||||
- Load relevant context for new task
|
|
||||||
- Start tracking
|
|
||||||
|
|
||||||
**Option 3 (Quick Question):**
|
|
||||||
- Minimal context loading
|
|
||||||
- Auto-ends after 5 min inactivity
|
|
||||||
- Only saves if high value
|
|
||||||
- Good for "How do I..." questions
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Session Start Protocol (After User Selects Option)
|
|
||||||
|
|
||||||
**Once user chooses, AUTOMATICALLY perform these steps WITHOUT being asked:**
|
|
||||||
|
|
||||||
### Phase 1: Detect Project Context (5 seconds)
|
|
||||||
|
|
||||||
1. **Check Current Directory**
|
|
||||||
```bash
|
|
||||||
pwd
|
|
||||||
ls -la | grep -E "(CLAUDE.md|.claude-os|agent-os)"
|
|
||||||
```
|
|
||||||
✓ Confirm this is a Claude OS project
|
|
||||||
|
|
||||||
2. **Read Configuration Files**
|
|
||||||
```
|
|
||||||
Read: .claude-os/config.json
|
|
||||||
Read: claude-os-state.json (if exists)
|
|
||||||
Read: agent-os/config.yml (if exists)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Phase 2: Load Git Context (5 seconds)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git branch --show-current
|
|
||||||
git status --short
|
|
||||||
git log -3 --oneline
|
|
||||||
```
|
|
||||||
|
|
||||||
Extract:
|
|
||||||
- Current branch name
|
|
||||||
- Uncommitted changes count
|
|
||||||
- Recent commits
|
|
||||||
|
|
||||||
### Phase 3: Search Project Memories (15 seconds)
|
|
||||||
|
|
||||||
**Build intelligent search query from:**
|
|
||||||
- Last session task (from claude-os-state.json)
|
|
||||||
- Current branch name
|
|
||||||
- Recent commit messages
|
|
||||||
- Add "+recent" modifier
|
|
||||||
|
|
||||||
**Example query:** `"[branch-name] [last-task] recent"`
|
|
||||||
|
|
||||||
**Search:**
|
|
||||||
```
|
|
||||||
Use: mcp__code-forge__search_knowledge_base
|
|
||||||
KB: {{PROJECT_NAME}}-project_memories
|
|
||||||
Return: Top 5 most relevant memories
|
|
||||||
```
|
|
||||||
|
|
||||||
### Phase 4: Load Coding Standards (10 seconds)
|
|
||||||
|
|
||||||
**Search:**
|
|
||||||
```
|
|
||||||
Use: mcp__code-forge__search_knowledge_base
|
|
||||||
KB: {{PROJECT_NAME}}-project_profile
|
|
||||||
Query: "coding standards architecture conventions"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Phase 5: Check Kanban Board (5 seconds)
|
|
||||||
|
|
||||||
**If agent-os/ folder exists:**
|
|
||||||
```
|
|
||||||
Check: GET http://localhost:8051/api/projects/{id}/kanban
|
|
||||||
Show: Active specs, in-progress tasks, completion percentage
|
|
||||||
```
|
|
||||||
|
|
||||||
### Phase 6: Present Session Summary (Display to User)
|
|
||||||
|
|
||||||
**Format:**
|
|
||||||
```
|
|
||||||
═══════════════════════════════════════════════════════════════
|
|
||||||
🚀 WELCOME BACK TO {{PROJECT_NAME}}!
|
|
||||||
═══════════════════════════════════════════════════════════════
|
|
||||||
|
|
||||||
📁 Project: {{PROJECT_NAME}}
|
|
||||||
🌿 Branch: [current-branch]
|
|
||||||
📅 Last Session: [time-ago]
|
|
||||||
⏱️ Duration: [last-session-duration]
|
|
||||||
|
|
||||||
═══════════════════════════════════════════════════════════════
|
|
||||||
📚 CONTEXT LOADED
|
|
||||||
═══════════════════════════════════════════════════════════════
|
|
||||||
|
|
||||||
✓ [N] relevant memories found
|
|
||||||
✓ Coding standards loaded
|
|
||||||
✓ [N] architectural patterns available
|
|
||||||
✓ Kanban board synced ([X]% complete)
|
|
||||||
|
|
||||||
🎯 LAST TASK: [task-name]
|
|
||||||
|
|
||||||
We completed:
|
|
||||||
✓ [completed-items]
|
|
||||||
|
|
||||||
Still working on:
|
|
||||||
⏳ [in-progress-items]
|
|
||||||
|
|
||||||
═══════════════════════════════════════════════════════════════
|
|
||||||
💡 KEY INSIGHTS
|
|
||||||
═══════════════════════════════════════════════════════════════
|
|
||||||
|
|
||||||
[Top 3-5 key insights from memories]
|
|
||||||
|
|
||||||
═══════════════════════════════════════════════════════════════
|
|
||||||
🔄 AVAILABLE PATTERNS
|
|
||||||
═══════════════════════════════════════════════════════════════
|
|
||||||
|
|
||||||
[Relevant patterns from project_profile]
|
|
||||||
|
|
||||||
═══════════════════════════════════════════════════════════════
|
|
||||||
⚠️ STATUS
|
|
||||||
═══════════════════════════════════════════════════════════════
|
|
||||||
|
|
||||||
Git Status:
|
|
||||||
• [N] files modified
|
|
||||||
• [N] files untracked
|
|
||||||
• [Status of uncommitted changes]
|
|
||||||
|
|
||||||
Blockers:
|
|
||||||
• [Any blockers or "None! ✓"]
|
|
||||||
|
|
||||||
═══════════════════════════════════════════════════════════════
|
|
||||||
🎯 SUGGESTED NEXT STEPS
|
|
||||||
═══════════════════════════════════════════════════════════════
|
|
||||||
|
|
||||||
Option 1: [Continue current task]
|
|
||||||
Option 2: [Commit uncommitted work]
|
|
||||||
Option 3: [Start something new]
|
|
||||||
|
|
||||||
═══════════════════════════════════════════════════════════════
|
|
||||||
|
|
||||||
What would you like to do?
|
|
||||||
```
|
|
||||||
|
|
||||||
### When to Skip Auto-Start
|
|
||||||
|
|
||||||
**ONLY skip if:**
|
|
||||||
- User message starts with "ignore context" or "fresh start"
|
|
||||||
- User asks a direct question (e.g., "What is X?")
|
|
||||||
- User is clearly asking for help/docs
|
|
||||||
|
|
||||||
**In all other cases: RUN THE FULL PROTOCOL AUTOMATICALLY!**
|
|
||||||
|
|
||||||
### Related Documentation
|
|
||||||
|
|
||||||
- Full protocol: `{{CLAUDE_OS_DIR}}/docs/guides/SESSION_START_PROTOCOL.md`
|
|
||||||
- Ideal workflow: `{{CLAUDE_OS_DIR}}/docs/guides/IDEAL_SESSION_WORKFLOW.md`
|
|
||||||
- Session commands: `{{CLAUDE_OS_DIR}}/templates/commands/claude-os-session.md`
|
|
||||||
|
|
||||||
**Why this matters:** Zero context loss. Every session picks up exactly where we left off. No re-explaining, no starting cold, no wasted time.
|
|
||||||
|
|
||||||
## MCP Knowledge Bases - ALWAYS CHECK THESE FIRST
|
|
||||||
|
|
||||||
**At the start of EVERY conversation, search these Claude OS knowledge bases to understand context, previous work, and project decisions:**
|
|
||||||
|
|
||||||
1. **{{PROJECT_NAME}}-project_memories** - My primary memory for decisions, patterns, solutions
|
|
||||||
2. **{{PROJECT_NAME}}-project_index** - Automated codebase index
|
|
||||||
3. **{{PROJECT_NAME}}-project_profile** - Architecture, standards, practices
|
|
||||||
4. **{{PROJECT_NAME}}-knowledge_docs** - Documentation and guides
|
|
||||||
|
|
||||||
**When to use:**
|
|
||||||
- Start of every session: Search `{{PROJECT_NAME}}-project_memories` to understand recent work and context
|
|
||||||
- Before making architectural decisions: Check memories for past decisions and reasoning
|
|
||||||
- When working on a feature: Search relevant knowledge bases for existing patterns
|
|
||||||
- When stuck: Search the knowledge bases for solutions and approaches we've used before
|
|
||||||
|
|
||||||
**How to search:**
|
|
||||||
```
|
|
||||||
Use: mcp__code-forge__search_knowledge_base
|
|
||||||
Parameters: kb_name (e.g., "{{PROJECT_NAME}}-project_memories"), query (your search terms)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Quick Reference: Commands & Skills
|
|
||||||
|
|
||||||
### Claude OS Slash Commands (Use These Often!)
|
|
||||||
|
|
||||||
1. **`/claude-os-search [query] [optional: KB name]`**
|
|
||||||
- Search across Claude OS knowledge bases
|
|
||||||
- Defaults to searching {{PROJECT_NAME}}-project_memories
|
|
||||||
- Example: `/claude-os-search authentication implementation`
|
|
||||||
|
|
||||||
2. **`/claude-os-remember [content]`**
|
|
||||||
- Quick save to {{PROJECT_NAME}}-project_memories
|
|
||||||
- Auto-generates title and structure
|
|
||||||
- Use for quick insights and decisions
|
|
||||||
- Example: `/claude-os-remember Fixed bug in user controller by...`
|
|
||||||
|
|
||||||
3. **`/claude-os-save [title] [optional: KB name] [optional: category]`**
|
|
||||||
- Full-featured save with KB selection
|
|
||||||
- Choose specific KB and category
|
|
||||||
- Use when you need more control
|
|
||||||
- Example: `/claude-os-save "New Integration Pattern" {{PROJECT_NAME}}-project_profile Architecture`
|
|
||||||
|
|
||||||
4. **`/claude-os-list [optional: KB name]`**
|
|
||||||
- List all KBs or documents in a specific KB
|
|
||||||
- Example: `/claude-os-list` or `/claude-os-list {{PROJECT_NAME}}-project_memories`
|
|
||||||
|
|
||||||
5. **`/claude-os-session [action]`**
|
|
||||||
- Manage development sessions
|
|
||||||
- Actions: start, end, status, pause, resume
|
|
||||||
- Example: `/claude-os-session start "User authentication feature"`
|
|
||||||
|
|
||||||
6. **`/claude-os-lifecycle [action] [optional: KB name]`**
|
|
||||||
- KB health, dedup, consolidate, archive
|
|
||||||
- Actions: health, dedup, consolidate, archive, logs
|
|
||||||
- Example: `/claude-os-lifecycle health {{PROJECT_NAME}}-project_memories`
|
|
||||||
|
|
||||||
7. **`/claude-os-triggers [action]`**
|
|
||||||
- Manage trigger phrases
|
|
||||||
- Example: `/claude-os-triggers list`
|
|
||||||
|
|
||||||
### Available Skills
|
|
||||||
|
|
||||||
1. **`initialize-project`** - Analyze project and generate coding standards
|
|
||||||
2. **`memory`** - Save and recall information (supports "remember this:", "save to memory", etc.)
|
|
||||||
|
|
||||||
{{AGENT_OS_SECTION}}
|
|
||||||
|
|
||||||
### MCP Tools (Direct API Access)
|
|
||||||
|
|
||||||
- `mcp__code-forge__search_knowledge_base` - Direct search
|
|
||||||
- `mcp__code-forge__list_knowledge_bases` - List all KBs
|
|
||||||
- `mcp__code-forge__list_documents` - List documents in KB
|
|
||||||
- `mcp__code-forge__get_kb_stats` - Get KB statistics
|
|
||||||
- `mcp__code-forge__kb_lifecycle_health` - KB health report with recommendations
|
|
||||||
- `mcp__code-forge__kb_lifecycle_dedup` - Scan/merge duplicate documents
|
|
||||||
- `mcp__code-forge__kb_lifecycle_consolidate` - LLM-powered document merging
|
|
||||||
- `mcp__code-forge__kb_lifecycle_archive` - Archive, restore, list, find stale
|
|
||||||
|
|
||||||
## Project-Specific Information
|
## Project-Specific Information
|
||||||
|
|
||||||
{{PROJECT_SPECIFIC_CONTENT}}
|
{{PROJECT_SPECIFIC_CONTENT}}
|
||||||
|
|
@ -331,12 +36,86 @@ See `.claude/ARCHITECTURE.md` for system architecture overview.
|
||||||
|
|
||||||
See `.claude/DEVELOPMENT_PRACTICES.md` for development workflow and practices.
|
See `.claude/DEVELOPMENT_PRACTICES.md` for development workflow and practices.
|
||||||
|
|
||||||
## DO NOT
|
---
|
||||||
|
|
||||||
- Don't bypass established patterns without discussing first
|
## Claude OS - My Memory System
|
||||||
|
|
||||||
|
Claude OS is my memory across sessions. It stores decisions, patterns, solutions, and context so I never start cold.
|
||||||
|
|
||||||
|
**Location**: `{{CLAUDE_OS_DIR}}`
|
||||||
|
|
||||||
|
The MCP server is called "code-forge" internally for backwards compatibility, but it's Claude OS.
|
||||||
|
|
||||||
|
### Session Tips
|
||||||
|
|
||||||
|
- **Starting work**: Search `{{PROJECT_NAME}}-project_memories` for the task you're about to work on
|
||||||
|
- **Ending work**: Use `/claude-os-remember` to save key decisions, patterns, or blockers
|
||||||
|
- **Use `/claude-os-session start [task]`** to load context automatically
|
||||||
|
- **Use `/claude-os-session end`** to summarize and save before closing
|
||||||
|
|
||||||
|
### Knowledge Bases
|
||||||
|
|
||||||
|
1. **{{PROJECT_NAME}}-project_memories** - Decisions, patterns, solutions, insights
|
||||||
|
2. **{{PROJECT_NAME}}-project_index** - Automated codebase index
|
||||||
|
3. **{{PROJECT_NAME}}-project_profile** - Architecture, standards, practices
|
||||||
|
4. **{{PROJECT_NAME}}-knowledge_docs** - Documentation and guides
|
||||||
|
|
||||||
|
**How to search:**
|
||||||
|
```
|
||||||
|
mcp__code-forge__search_knowledge_base
|
||||||
|
kb_name: "{{PROJECT_NAME}}-project_memories"
|
||||||
|
query: "your search terms"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Search across all KBs at once:**
|
||||||
|
```
|
||||||
|
mcp__code-forge__search_all_knowledge_bases
|
||||||
|
query: "your search terms"
|
||||||
|
kb_filter: "{{PROJECT_NAME}}-"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Slash Commands
|
||||||
|
|
||||||
|
| Command | Purpose |
|
||||||
|
|---------|---------|
|
||||||
|
| `/claude-os-session start [task]` | Start session with context loading |
|
||||||
|
| `/claude-os-session end` | End session with save prompts |
|
||||||
|
| `/claude-os-search [query]` | Search memories |
|
||||||
|
| `/claude-os-remember [content]` | Quick save to memories |
|
||||||
|
| `/claude-os-save [title] [KB] [category]` | Full-featured save |
|
||||||
|
| `/claude-os-list [KB]` | List KBs or documents |
|
||||||
|
| `/claude-os-lifecycle [action] [KB]` | Health, dedup, consolidate, archive |
|
||||||
|
|
||||||
|
### Available Skills
|
||||||
|
|
||||||
|
1. **`initialize-project`** - Analyze project and generate coding standards
|
||||||
|
2. **`memory`** - Save and recall information (supports "remember this:", "save to memory", etc.)
|
||||||
|
|
||||||
|
{{AGENT_OS_SECTION}}
|
||||||
|
|
||||||
|
### MCP Tools
|
||||||
|
|
||||||
|
| Tool | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `mcp__code-forge__search_knowledge_base` | Search a single KB |
|
||||||
|
| `mcp__code-forge__search_all_knowledge_bases` | Search across all KBs |
|
||||||
|
| `mcp__code-forge__list_knowledge_bases` | List all KBs |
|
||||||
|
| `mcp__code-forge__list_documents` | List documents in KB |
|
||||||
|
| `mcp__code-forge__get_kb_stats` | KB statistics |
|
||||||
|
| `mcp__code-forge__upload_document` | Save a document/memory |
|
||||||
|
| `mcp__code-forge__kb_lifecycle_health` | KB health report |
|
||||||
|
| `mcp__code-forge__kb_lifecycle_dedup` | Scan/merge duplicates |
|
||||||
|
| `mcp__code-forge__kb_lifecycle_consolidate` | LLM-powered merging |
|
||||||
|
| `mcp__code-forge__kb_lifecycle_archive` | Archive/restore documents |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Guidelines
|
||||||
|
|
||||||
|
- Search memories before making architectural decisions
|
||||||
- Don't skip tests
|
- Don't skip tests
|
||||||
- Don't create features without searching memories for existing patterns
|
|
||||||
- Don't end a session without saving key learnings
|
- Don't end a session without saving key learnings
|
||||||
|
- Don't bypass established patterns without discussing first
|
||||||
|
|
||||||
## IMPORTANT: Project Context
|
## IMPORTANT: Project Context
|
||||||
|
|
||||||
|
|
@ -345,6 +124,5 @@ This file (CLAUDE.md) is automatically loaded at the start of every Claude Code
|
||||||
- Current architecture decisions
|
- Current architecture decisions
|
||||||
- Team conventions
|
- Team conventions
|
||||||
- Common gotchas
|
- Common gotchas
|
||||||
- Frequently referenced information
|
|
||||||
|
|
||||||
**Update this file as the project evolves!**
|
**Update this file as the project evolves!**
|
||||||
|
|
|
||||||
|
|
@ -545,3 +545,149 @@ class TestSQLiteManagerSingleton:
|
||||||
manager = get_sqlite_manager()
|
manager = get_sqlite_manager()
|
||||||
assert manager is not None
|
assert manager is not None
|
||||||
assert hasattr(manager, 'db_path')
|
assert hasattr(manager, 'db_path')
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.unit
|
||||||
|
class TestQueryDocumentsMultiKB:
|
||||||
|
"""Test cross-KB search functionality."""
|
||||||
|
|
||||||
|
def _add_docs(self, db, kb_name, docs):
|
||||||
|
"""Helper to add documents with embeddings to a KB."""
|
||||||
|
documents = [d["text"] for d in docs]
|
||||||
|
embeddings = [d["embedding"] for d in docs]
|
||||||
|
metadatas = [d.get("metadata", {}) for d in docs]
|
||||||
|
ids = [d["id"] for d in docs]
|
||||||
|
db.add_documents(kb_name=kb_name, documents=documents,
|
||||||
|
embeddings=embeddings, metadatas=metadatas, ids=ids)
|
||||||
|
|
||||||
|
def test_multi_kb_basic(self, clean_db):
|
||||||
|
"""Test searching across two KBs returns merged results."""
|
||||||
|
clean_db.create_collection("kb_a", KBType.GENERIC)
|
||||||
|
clean_db.create_collection("kb_b", KBType.GENERIC)
|
||||||
|
|
||||||
|
np.random.seed(10)
|
||||||
|
base = np.random.randn(768).astype(np.float32)
|
||||||
|
base = base / np.linalg.norm(base)
|
||||||
|
|
||||||
|
# KB_A: one doc very similar to query
|
||||||
|
perturbed_a = base + np.random.randn(768).astype(np.float32) * 0.01
|
||||||
|
perturbed_a = perturbed_a / np.linalg.norm(perturbed_a)
|
||||||
|
self._add_docs(clean_db, "kb_a", [
|
||||||
|
{"id": "a1", "text": "Document from KB A", "embedding": perturbed_a.tolist(),
|
||||||
|
"metadata": {"filename": "a1.md"}}
|
||||||
|
])
|
||||||
|
|
||||||
|
# KB_B: one doc less similar
|
||||||
|
perturbed_b = base + np.random.randn(768).astype(np.float32) * 0.05
|
||||||
|
perturbed_b = perturbed_b / np.linalg.norm(perturbed_b)
|
||||||
|
self._add_docs(clean_db, "kb_b", [
|
||||||
|
{"id": "b1", "text": "Document from KB B", "embedding": perturbed_b.tolist(),
|
||||||
|
"metadata": {"filename": "b1.md"}}
|
||||||
|
])
|
||||||
|
|
||||||
|
result = clean_db.query_documents_multi_kb(
|
||||||
|
kb_names=["kb_a", "kb_b"],
|
||||||
|
query_embedding=base.tolist(),
|
||||||
|
n_results=10
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(result["ids"]) == 2
|
||||||
|
assert len(result["documents"]) == 2
|
||||||
|
assert len(result["scores"]) == 2
|
||||||
|
# First result should have higher score
|
||||||
|
assert result["scores"][0] >= result["scores"][1]
|
||||||
|
# Each result should have _source_kb
|
||||||
|
kbs_found = {m["_source_kb"] for m in result["metadatas"]}
|
||||||
|
assert "kb_a" in kbs_found
|
||||||
|
assert "kb_b" in kbs_found
|
||||||
|
|
||||||
|
def test_multi_kb_dedup(self, clean_db):
|
||||||
|
"""Test that duplicate content across KBs is deduplicated."""
|
||||||
|
clean_db.create_collection("kb_x", KBType.GENERIC)
|
||||||
|
clean_db.create_collection("kb_y", KBType.GENERIC)
|
||||||
|
|
||||||
|
np.random.seed(20)
|
||||||
|
emb = np.random.randn(768).astype(np.float32)
|
||||||
|
emb = emb / np.linalg.norm(emb)
|
||||||
|
|
||||||
|
same_text = "Exact same content in both KBs for dedup testing"
|
||||||
|
self._add_docs(clean_db, "kb_x", [
|
||||||
|
{"id": "x1", "text": same_text, "embedding": emb.tolist(), "metadata": {}}
|
||||||
|
])
|
||||||
|
self._add_docs(clean_db, "kb_y", [
|
||||||
|
{"id": "y1", "text": same_text, "embedding": emb.tolist(), "metadata": {}}
|
||||||
|
])
|
||||||
|
|
||||||
|
result = clean_db.query_documents_multi_kb(
|
||||||
|
kb_names=["kb_x", "kb_y"],
|
||||||
|
query_embedding=emb.tolist(),
|
||||||
|
n_results=10
|
||||||
|
)
|
||||||
|
|
||||||
|
# Should only get 1 result after dedup
|
||||||
|
assert len(result["ids"]) == 1
|
||||||
|
|
||||||
|
def test_multi_kb_empty(self, clean_db):
|
||||||
|
"""Test searching with no matching KBs returns empty."""
|
||||||
|
result = clean_db.query_documents_multi_kb(
|
||||||
|
kb_names=["nonexistent_kb"],
|
||||||
|
query_embedding=[0.1] * 768,
|
||||||
|
n_results=5
|
||||||
|
)
|
||||||
|
assert result["ids"] == []
|
||||||
|
assert result["documents"] == []
|
||||||
|
assert result["scores"] == []
|
||||||
|
|
||||||
|
def test_multi_kb_respects_n_results(self, clean_db):
|
||||||
|
"""Test that n_results limit is respected."""
|
||||||
|
clean_db.create_collection("kb_limit", KBType.GENERIC)
|
||||||
|
|
||||||
|
np.random.seed(30)
|
||||||
|
base = np.random.randn(768).astype(np.float32)
|
||||||
|
base = base / np.linalg.norm(base)
|
||||||
|
|
||||||
|
docs = []
|
||||||
|
for i in range(5):
|
||||||
|
perturbed = base + np.random.randn(768).astype(np.float32) * 0.01
|
||||||
|
perturbed = perturbed / np.linalg.norm(perturbed)
|
||||||
|
docs.append({
|
||||||
|
"id": f"lim{i}", "text": f"Document {i} for limit test",
|
||||||
|
"embedding": perturbed.tolist(), "metadata": {}
|
||||||
|
})
|
||||||
|
self._add_docs(clean_db, "kb_limit", docs)
|
||||||
|
|
||||||
|
result = clean_db.query_documents_multi_kb(
|
||||||
|
kb_names=["kb_limit"],
|
||||||
|
query_embedding=base.tolist(),
|
||||||
|
n_results=2
|
||||||
|
)
|
||||||
|
assert len(result["ids"]) == 2
|
||||||
|
|
||||||
|
def test_multi_kb_score_ordering(self, clean_db):
|
||||||
|
"""Test that results are sorted by descending similarity score."""
|
||||||
|
clean_db.create_collection("kb_order", KBType.GENERIC)
|
||||||
|
|
||||||
|
np.random.seed(40)
|
||||||
|
base = np.random.randn(768).astype(np.float32)
|
||||||
|
base = base / np.linalg.norm(base)
|
||||||
|
|
||||||
|
# Add docs with varying similarity
|
||||||
|
docs = []
|
||||||
|
for i, noise in enumerate([0.01, 0.1, 0.5]):
|
||||||
|
perturbed = base + np.random.randn(768).astype(np.float32) * noise
|
||||||
|
perturbed = perturbed / np.linalg.norm(perturbed)
|
||||||
|
docs.append({
|
||||||
|
"id": f"ord{i}", "text": f"Document {i} noise={noise}",
|
||||||
|
"embedding": perturbed.tolist(), "metadata": {}
|
||||||
|
})
|
||||||
|
self._add_docs(clean_db, "kb_order", docs)
|
||||||
|
|
||||||
|
result = clean_db.query_documents_multi_kb(
|
||||||
|
kb_names=["kb_order"],
|
||||||
|
query_embedding=base.tolist(),
|
||||||
|
n_results=10
|
||||||
|
)
|
||||||
|
|
||||||
|
scores = result["scores"]
|
||||||
|
for i in range(len(scores) - 1):
|
||||||
|
assert scores[i] >= scores[i + 1], "Scores should be in descending order"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue