Initial commit: Claude Code Project Tracker

Add comprehensive development intelligence system that tracks:
- Development sessions with automatic start/stop
- Full conversation history with semantic search
- Tool usage and file operation analytics
- Think time and engagement analysis
- Git activity correlation
- Learning pattern recognition
- Productivity insights and metrics

Features:
- FastAPI backend with SQLite database
- Modern web dashboard with interactive charts
- Claude Code hook integration for automatic tracking
- Comprehensive test suite with 100+ tests
- Complete API documentation (OpenAPI/Swagger)
- Privacy-first design with local data storage

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Ryan Malloy 2025-08-11 02:59:21 -06:00
commit 44ed9936b7
48 changed files with 9707 additions and 0 deletions

69
app/models/project.py Normal file
View file

@ -0,0 +1,69 @@
"""
Project model for tracking development projects.
"""
from datetime import datetime
from typing import Optional, List
from sqlalchemy import String, Text, Integer, DateTime, JSON
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.sql import func
from .base import Base, TimestampMixin
class Project(Base, TimestampMixin):
"""
Represents a development project tracked by Claude Code.
A project is typically identified by its filesystem path and may
correspond to a git repository.
"""
__tablename__ = "projects"
# Primary key
id: Mapped[int] = mapped_column(primary_key=True)
# Core project information
name: Mapped[str] = mapped_column(String(255), nullable=False)
path: Mapped[str] = mapped_column(Text, nullable=False, unique=True, index=True)
git_repo: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
languages: Mapped[Optional[List[str]]] = mapped_column(JSON, nullable=True)
# Activity tracking
last_session: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True, index=True)
total_sessions: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
total_time_minutes: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
files_modified_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
lines_changed_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
# Relationships
sessions: Mapped[List["Session"]] = relationship(
"Session",
back_populates="project",
cascade="all, delete-orphan",
order_by="Session.start_time.desc()"
)
def __repr__(self) -> str:
return f"<Project(id={self.id}, name='{self.name}', path='{self.path}')>"
@property
def is_git_repo(self) -> bool:
"""Check if this project is a git repository."""
return self.git_repo is not None and self.git_repo != ""
@property
def primary_language(self) -> Optional[str]:
"""Get the primary programming language for this project."""
if self.languages and len(self.languages) > 0:
return self.languages[0]
return None
def update_stats(self, session_duration_minutes: int, files_count: int, lines_count: int) -> None:
"""Update project statistics after a session."""
self.total_sessions += 1
self.total_time_minutes += session_duration_minutes
self.files_modified_count += files_count
self.lines_changed_count += lines_count
self.last_session = func.now()