Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .claude/settings.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
"Bash(black . && echo \"✅ All files formatted!\")",
"Bash(pip install:*)",
"Bash(python -m black . --quiet && echo \"✅ All files formatted!\")",
"Bash(git add:*)"
"Bash(git add:*)",
"Bash(python -m black --check . && echo \"✅ All files pass Black formatting check!\")",
"Bash(gh repo:*)",
"Bash(find /d/Claude_memeory -name \"*.py\" -type f ! -path \"*/venv/*\" | xargs wc -l | tail -1)"
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This command hardcodes a machine-specific absolute path and appears to have a typo (Claude_memeory). This makes the settings non-portable and likely broken for other developers/CI. Consider removing the absolute path, fixing the spelling, or avoiding committing local-only commands into the repo.

Suggested change
"Bash(find /d/Claude_memeory -name \"*.py\" -type f ! -path \"*/venv/*\" | xargs wc -l | tail -1)"
"Bash(find . -name \"*.py\" -type f ! -path \"*/venv/*\" | xargs wc -l | tail -1)"

Copilot uses AI. Check for mistakes.
]
}
}
194 changes: 194 additions & 0 deletions FEATURES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# Claude Memory - New Features

## Recently Added (Latest Update)

### 1. Audit Logging System

Track all team actions with detailed audit logs.

**Features:**
- Automatic logging of all API actions
- User and action filtering
- Team statistics and activity summaries
- Persistent audit trail (stored in `.memory/audit/audit.jsonl`)

**Available Actions:**
- `remember` - Store memory
- `recall` - Search memory
- `forget` - Delete memory
- `add_rule` - Create rules
- `handoff_share` - Share work
- `handoff_pickup` - Pick up work
- `session_save` - Save session
- `user_created` - User management
- `api_key_generated` - Security events

**API Endpoints:**
```
GET /audit/logs - Get audit logs with filtering
GET /audit/stats - Get team statistics
GET /audit/user/<username> - Get user's activity
```

### 2. Web Dashboard

Modern React-based dashboard for team collaboration.

**Pages:**
- **Dashboard** - Overview with stats and recent activity
- **Audit Logs** - Full audit trail with search and filtering
- **Team Members** - View all team members and roles
- **Memories** - Search and manage team decisions
- **Rules** - View team coding standards

**Features:**
- Real-time statistics
- Search and filtering
- Role-based color coding
- Responsive design
- Dark theme (modern UI/UX)

**Tech Stack:**
- React 18 + Vite
- Tailwind CSS for styling
- Lucide React icons
- Axios for HTTP

**Setup:**
```bash
cd web
npm install
npm run dev
```

Then open http://localhost:3000

## All Current Features

### Core Features
- Session sharing and handoffs between team members
- Team rules and personal coding standards
- Vector search for memories (ChromaDB)
- Team member profiles and roles
- Organization-wide policies
- Session summaries and history
- Role-based suggestions
- Rules synchronization

### Admin Features
- API key management (generate, revoke, regenerate)
- User management (create, delete)
- Team administration
- Organization setup

### Team Collaboration
- Handoff sharing with context
- Pickup and complete workflows
- Cross-team knowledge sharing
- Member expertise tracking

### Memory System
- Store decisions with categories
- Semantic search with vector embeddings
- Importance levels (critical, high, normal, low)
- Tag-based organization
- Session summaries

### Audit & Compliance
- Complete audit trail of all actions
- User activity tracking
- Team statistics
- Action filtering and search

### Dashboard & UI
- Web-based management interface
- Real-time activity feeds
- Team insights and statistics
- Search and filtering capabilities
- Responsive design

## Upcoming Features (Roadmap)

**Tier 1 - High Priority:**
- [ ] Notifications and webhooks (Slack integration)
- [ ] Export/Backup functionality (Markdown, PDF, JSON)
- [ ] Decision versioning and history tracking
- [ ] Conflict detection for contradicting rules

**Tier 2 - Medium Priority:**
- [ ] Code integration (parse comments, commits)
- [ ] Team insights reports (weekly/monthly)
- [ ] Fine-tuned models on team knowledge
- [ ] Decision templates and workflows

**Tier 3 - Nice to Have:**
- [ ] Multi-server sync for HA
- [ ] Access control (private vs public memories)
- [ ] Team voting on decisions
- [ ] Mobile app
- [ ] Git repository integration

## Architecture

```
Claude Memory
├── memory_server/
│ ├── server.py (MCP server)
│ ├── server_http.py (HTTP server with audit)
│ ├── server_mcp_client.py (MCP client)
│ └── audit/ (new)
│ └── audit_logger.py (audit system)
├── scripts/
│ ├── memory_utils.py (core storage)
│ ├── manage_team.py (team management)
│ └── summarize_session.py
├── web/ (new)
│ ├── src/
│ │ ├── pages/ (Dashboard, Audit, Team, Rules, Memories)
│ │ ├── components/ (Navbar, Sidebar, Card)
│ │ ├── api/ (HTTP client)
│ │ └── App.jsx
│ ├── package.json
│ └── vite.config.js
├── client/
│ ├── server_mcp_client.py
│ ├── setup_mcp.bat
│ └── requirements.txt
└── .memory/
├── audit/ (new - audit logs)
├── chroma_db/ (vector database)
├── team.json (team data)
└── sessions/ (session history)
```

## Quick Start

### Server Setup
```bash
pip install -r memory_server/requirements.txt
python memory_server/server_http.py --host 0.0.0.0 --port 8765
curl -X POST http://localhost:8765/admin/setup
python scripts/manage_team.py create "Alice" backend
```

### Web Dashboard
```bash
cd web
npm install
npm run dev
# Visit http://localhost:3000
```

### Client Setup
```bash
cd client
pip install -r requirements.txt
setup_mcp.bat
```

## Documentation

- [README.md](README.md) - Main project documentation
- [client/README.md](client/README.md) - Client setup guide
- [web/README.md](web/README.md) - Dashboard documentation
- [CONTRIBUTING.md](CONTRIBUTING.md) - Contribution guidelines
150 changes: 150 additions & 0 deletions memory_server/audit/audit_logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
"""
Audit logging system for Claude Memory.
Tracks all user actions for compliance and debugging.
"""

import json
from datetime import datetime
from pathlib import Path
from typing import Optional, Any
from enum import Enum


class AuditAction(Enum):
"""Types of actions to audit."""
REMEMBER = "remember"
RECALL = "recall"
FORGET = "forget"
ADD_RULE = "add_rule"
DELETE_RULE = "delete_rule"
HANDOFF_SHARE = "handoff_share"
HANDOFF_PICKUP = "handoff_pickup"
SESSION_SAVE = "session_save"
SESSION_LOAD = "session_load"
USER_LOGIN = "user_login"
USER_CREATED = "user_created"
USER_DELETED = "user_deleted"
API_KEY_GENERATED = "api_key_generated"
API_KEY_REVOKED = "api_key_revoked"


class AuditLogger:
"""Log all actions for audit trail."""

def __init__(self, log_dir: str = ".memory/audit"):
self.log_dir = Path(log_dir)
self.log_dir.mkdir(parents=True, exist_ok=True)
self.log_file = self.log_dir / "audit.jsonl"

def log(
self,
action: AuditAction,
user: str,
details: Optional[dict] = None,
status: str = "success",
error: Optional[str] = None,
) -> dict:
"""
Log an action.

Args:
action: Type of action (from AuditAction enum)
user: Username who performed action
details: Additional context about the action
status: "success" or "failure"
error: Error message if failed
"""
entry = {
"timestamp": datetime.utcnow().isoformat(),
"action": action.value,
"user": user,
"status": status,
"details": details or {},
"error": error,
Comment on lines +56 to +63
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Timestamps are written as datetime.utcnow().isoformat() without a timezone designator. JS Date parsing will treat this as local time, leading to incorrect displayed timestamps. Prefer timezone-aware timestamps (e.g., include Z/UTC offset) so clients interpret times correctly.

Copilot uses AI. Check for mistakes.
}

# Append to log file
with open(self.log_file, "a") as f:
f.write(json.dumps(entry) + "\n")

Comment on lines +66 to +69
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Audit log writes are done by appending to a shared file without any locking. Under a threaded/multi-worker server (or concurrent requests), writes can interleave and corrupt JSONL lines. Add a process/thread-safe locking strategy or write via an atomic append mechanism to keep the log valid.

Copilot uses AI. Check for mistakes.
return entry

def get_audit_trail(
self,
user: Optional[str] = None,
action: Optional[str] = None,
limit: int = 100,
) -> list[dict]:
"""
Retrieve audit logs filtered by user and/or action.

Args:
user: Filter by username (optional)
action: Filter by action type (optional)
limit: Max results to return
"""
if not self.log_file.exists():
return []

logs = []
with open(self.log_file, "r") as f:
for line in f:
if not line.strip():
continue
entry = json.loads(line)

if user and entry["user"] != user:
continue
if action and entry["action"] != action:
continue

logs.append(entry)
Comment on lines +89 to +101
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_audit_trail assumes every line is valid JSON; a single partial/corrupt line will raise JSONDecodeError and break the endpoint. Add per-line error handling (skip/bucket invalid lines) so reads are resilient, especially given concurrent writes.

Copilot uses AI. Check for mistakes.

# Return most recent first
return sorted(
logs, key=lambda x: x["timestamp"], reverse=True
)[:limit]

def get_user_activity(self, user: str, limit: int = 50) -> dict:
"""Get summary of user's recent activity."""
logs = self.get_audit_trail(user=user, limit=limit)

action_counts = {}
for log in logs:
action = log["action"]
action_counts[action] = action_counts.get(action, 0) + 1

return {
"user": user,
"total_actions": len(logs),
"action_summary": action_counts,
"recent_actions": logs[:10],
}

def get_team_stats(self) -> dict:
"""Get overall team statistics."""
if not self.log_file.exists():
return {
"total_actions": 0,
"active_users": [],
"action_breakdown": {},
}

logs = []
with open(self.log_file, "r") as f:
logs = [json.loads(line) for line in f if line.strip()]
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_team_stats parses the entire file with json.loads in a list comprehension without error handling. If a single line is malformed, stats will 500. Consider streaming with try/except per line so stats remain available even if the log contains a bad entry.

Suggested change
logs = [json.loads(line) for line in f if line.strip()]
for line in f:
if not line.strip():
continue
try:
logs.append(json.loads(line))
except json.JSONDecodeError:
continue

Copilot uses AI. Check for mistakes.

users = set()
actions = {}

for log in logs:
users.add(log["user"])
action = log["action"]
actions[action] = actions.get(action, 0) + 1

return {
"total_actions": len(logs),
"active_users": sorted(list(users)),
"action_breakdown": actions,
"last_action": logs[-1]["timestamp"] if logs else None,
Comment on lines +133 to +149
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_team_stats loads the entire audit log file into memory, which won’t scale as the audit trail grows. Consider streaming the file and aggregating counts incrementally (and/or limiting to a time window) to keep memory usage predictable.

Suggested change
logs = []
with open(self.log_file, "r") as f:
logs = [json.loads(line) for line in f if line.strip()]
users = set()
actions = {}
for log in logs:
users.add(log["user"])
action = log["action"]
actions[action] = actions.get(action, 0) + 1
return {
"total_actions": len(logs),
"active_users": sorted(list(users)),
"action_breakdown": actions,
"last_action": logs[-1]["timestamp"] if logs else None,
total_actions = 0
users = set()
actions = {}
last_action = None
with open(self.log_file, "r") as f:
for line in f:
if not line.strip():
continue
log = json.loads(line)
total_actions += 1
users.add(log["user"])
action = log["action"]
actions[action] = actions.get(action, 0) + 1
last_action = log["timestamp"]
return {
"total_actions": total_actions,
"active_users": sorted(list(users)),
"action_breakdown": actions,
"last_action": last_action,

Copilot uses AI. Check for mistakes.
}
Loading
Loading