claude-code-tracker/import_claude_data.py
Ryan Malloy bec1606c86 Add comprehensive documentation system and tool call tracking
## Documentation System
- Create complete documentation hub at /dashboard/docs with:
  - Getting Started guide with quick setup and troubleshooting
  - Hook Setup Guide with platform-specific configurations
  - API Reference with all endpoints and examples
  - FAQ with searchable questions and categories
- Add responsive design with interactive features
- Update navigation in base template

## Tool Call Tracking
- Add ToolCall model for tracking Claude Code tool usage
- Create /api/tool-calls endpoints for recording and analytics
- Add tool_call hook type with auto-session detection
- Include tool calls in project statistics and recalculation
- Track tool names, parameters, execution time, and success rates

## Project Enhancements
- Add project timeline and statistics pages (fix 404 errors)
- Create recalculation script for fixing zero statistics
- Update project stats to include tool call counts
- Enhance session model with tool call relationships

## Infrastructure
- Switch from requirements.txt to pyproject.toml/uv.lock
- Add data import functionality for claude.json files
- Update database connection to include all new models
- Add comprehensive API documentation

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-11 05:58:27 -06:00

154 lines
4.9 KiB
Python

#!/usr/bin/env python3
"""
Command-line tool to import data from .claude.json file.
Usage:
python import_claude_data.py [--file path/to/.claude.json] [--preview]
"""
import asyncio
import argparse
import sys
from pathlib import Path
from app.database.connection import async_session_maker, init_database
from app.api.importer import ClaudeJsonImporter
async def preview_import(file_path: str):
"""Preview what would be imported."""
print(f"🔍 Previewing import from: {file_path}")
print("=" * 50)
try:
import json
import os
if not os.path.exists(file_path):
print(f"❌ File not found: {file_path}")
return False
with open(file_path, 'r', encoding='utf-8') as f:
claude_data = json.load(f)
file_size_mb = round(os.path.getsize(file_path) / (1024 * 1024), 2)
print(f"📁 File size: {file_size_mb} MB")
print(f"🚀 Total Claude Code startups: {claude_data.get('numStartups', 0)}")
print(f"📅 First start time: {claude_data.get('firstStartTime', 'N/A')}")
print(f"📊 Prompt queue uses: {claude_data.get('promptQueueUseCount', 0)}")
if "projects" in claude_data:
projects = claude_data["projects"]
print(f"📂 Projects found: {len(projects)}")
# Show first few project paths
paths = list(projects.keys())[:5]
for path in paths:
history_count = len(projects[path].get("history", []))
print(f"{path} ({history_count} history entries)")
if len(projects) > 5:
print(f" ... and {len(projects) - 5} more projects")
# Count total history entries
total_history = sum(len(proj.get("history", [])) for proj in projects.values())
print(f"💬 Total conversation history entries: {total_history}")
print("\n✅ Preview completed successfully!")
return True
except Exception as e:
print(f"❌ Preview failed: {e}")
return False
async def run_import(file_path: str):
"""Run the actual import process."""
print(f"📥 Starting import from: {file_path}")
print("=" * 50)
# Initialize database tables first
print("🔧 Initializing database...")
await init_database()
print("✅ Database initialized")
async with async_session_maker() as db:
try:
importer = ClaudeJsonImporter(db)
results = await importer.import_from_file(file_path)
print("🎉 Import completed successfully!")
print(f"📂 Projects imported: {results['projects_imported']}")
print(f"⏱️ Sessions estimated: {results['sessions_estimated']}")
print(f"💬 Conversations imported: {results['conversations_imported']}")
if results['errors']:
print(f"\n⚠️ Warnings/Errors ({len(results['errors'])}):")
for error in results['errors']:
print(f"{error}")
print("\n🚀 You can now view your imported data at: http://localhost:8000")
return True
except Exception as e:
print(f"❌ Import failed: {e}")
return False
def main():
"""Main entry point."""
parser = argparse.ArgumentParser(
description="Import Claude Code data from .claude.json file",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python import_claude_data.py --preview
python import_claude_data.py --file ~/.claude.json
python import_claude_data.py --file ~/.claude.json --preview
"""
)
parser.add_argument(
"--file",
type=str,
default=None,
help="Path to .claude.json file (default: ~/.claude.json)"
)
parser.add_argument(
"--preview",
action="store_true",
help="Preview what would be imported without actually importing"
)
args = parser.parse_args()
# Determine file path
if args.file:
file_path = args.file
else:
file_path = str(Path.home() / ".claude.json")
print("🤖 Claude Code Project Tracker - Data Importer")
print("=" * 50)
if args.preview:
success = asyncio.run(preview_import(file_path))
else:
print("⚠️ This will import data into your Claude Code Project Tracker database.")
print(" Make sure the tracker server is not running during import.")
print()
confirm = input("Continue with import? (y/N): ").lower().strip()
if confirm != 'y':
print("Import cancelled.")
sys.exit(0)
success = asyncio.run(run_import(file_path))
sys.exit(0 if success else 1)
if __name__ == "__main__":
main()