## 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>
154 lines
4.9 KiB
Python
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() |