Claude Project Chat Interface is a generalized local web application that provides an intuitive chat interface for interacting with ANY Claude Project. Supports both the official Anthropic API and direct Claude.ai web access with cookie authentication.
- Backend: Python 3.11+, Flask 3.0
- Frontend: HTML5, Tailwind CSS 3.4, Vanilla JavaScript
- AI Integration:
- Anthropic Claude API (Python SDK 0.18+) - Official API
- Claude.ai Web Client (curl_cffi) - Direct web access with cookie auth
- File Processing: PyPDF2, python-docx, beautifulsoup4
- Environment: python-dotenv for configuration
- Storage: Local filesystem (no database required)
claude_project_chat/
├── app.py # Flask server with API routes
├── config.py # Project configuration
├── project_config.yaml # Project-specific settings (prompts, file types, etc)
├── custom_prompts.yaml # User's custom templates (gitignored)
├── requirements.txt # Python dependencies
├── .env # Environment variables (API keys/cookies)
├── .gitignore # Git ignore patterns
├── README.md # Setup and usage instructions
├── static/
│ ├── css/
│ │ └── styles.css # Custom styles
│ ├── js/
│ │ ├── app.js # Frontend logic and API client
│ │ └── prompt-builder.js # Template UI + Project Manager
│ └── uploads/ # Temporary file storage (auto-created)
├── templates/
│ └── index.html # Main chat interface
└── utils/
├── __init__.py # Package initialization
├── claude_client.py # Official Anthropic API wrapper
├── claude_web_client.py # Claude.ai direct web client (cookie auth)
├── tool_handler.py # Tool execution handler for web client
├── file_processor.py # File upload and content extraction
├── url_fetcher.py # URL content retrieval
├── prompt_templates.py # 20+ built-in templates
├── prompt_compiler.py # Template variable compilation
└── config_loader.py # Project configuration loader
Implemented:
- Dual Connection Modes:
- Claude.ai Web Client (cookie auth) - Access Projects with knowledge bases
- Official Anthropic API - Standard Claude access
- Project Selector - Switch between Claude Projects on the fly
- New Chat Button - Start fresh conversations within projects
- Settings Modal - Manage projects, templates, connection settings
- 20+ Built-in Templates - Analysis, research, content, technical
- Configuration-driven project setup (YAML-based)
- File upload handling (PDF, DOCX, TXT, MD, configurable)
- Chat history with conversation threading
- URL content fetching (optional)
- URL sanitization (strips markdown formatting)
Configurable Per Project:
- Project name and description
- Custom prompt templates with variables
- File type requirements
- UI branding (title, colors)
- Feature flags (URL fetching, file upload, etc)
Pending:
- Session persistence (SQLite database)
- Export functionality (PDF/CSV reports)
- Batch analysis processing
- Analysis history dashboard
- Full tool execution loop for web client
This interface is project-agnostic. Configure it for any Claude Project by editing project_config.yaml.
project_config.yaml
# Project Identity
project:
name: "My Claude Project"
description: "Custom Claude Project chat interface"
claude_project_id: "${CLAUDE_PROJECT_ID}" # From .env
# UI Customization
ui:
title: "My Project Chat"
subtitle: "Powered by Claude"
primary_color: "#3b82f6" # Tailwind blue-500
show_logo: false
logo_path: ""
# Feature Flags
features:
file_upload: true
url_fetching: true
multi_file: true
conversation_history: true
export_chat: false
# File Processing
files:
allowed_extensions:
- pdf
- docx
- txt
- md
max_size_mb: 10
max_files: 5
# Preconfigured Prompts
prompts:
- id: "general_chat"
label: "General Chat"
template: "{user_input}"
requires_files: false
requires_input: true
placeholder: "Ask me anything..."
- id: "document_analysis"
label: "Analyze Document"
template: "Please analyze this document: {user_input}"
requires_files: true
min_files: 1
placeholder: "Optional: What to focus on..."
- id: "compare_documents"
label: "Compare Documents"
template: "Compare these documents and highlight key differences"
requires_files: true
min_files: 2
- id: "url_analysis"
label: "Analyze Website"
template: "Analyze this website: {url}"
requires_url: true
placeholder: "Enter URL..."
# Custom Instructions (prepended to every request)
system_context: |
You are a helpful assistant working within a Claude Project.
Follow the project's custom instructions and knowledge base.Example 1: Concept Clarity Analysis
project:
name: "Concept Clarity System"
prompts:
- id: "full_analysis"
label: "Full Positioning Clarity Analysis"
template: "Analyze positioning clarity across these materials"
requires_files: true
min_files: 2Example 2: Code Review Assistant
project:
name: "Code Review Bot"
files:
allowed_extensions:
- py
- js
- ts
- java
- cpp
prompts:
- id: "review"
label: "Review Code"
template: "Review this code for quality, security, and best practices"
requires_files: trueExample 3: Research Assistant
project:
name: "Research Helper"
features:
url_fetching: true
prompts:
- id: "summarize"
label: "Summarize Research"
template: "Summarize key findings from these sources"
requires_files: true
requires_url: true- Python 3.11+ (3.11 recommended for best compatibility)
- pip (Python package installer)
- Anthropic API Key with Claude Project access
- Claude Project UUID for your Concept Clarity project
# 1. Create project directory
mkdir claude_project_chat
cd claude_project_chat
# 2. Create virtual environment
python3.11 -m venv venv
# 3. Activate virtual environment
source venv/bin/activate # macOS/Linux
# OR
venv\Scripts\activate # Windows
# 4. Install dependencies
pip install -r requirements.txt
# 5. Create .env file
touch .envAdd to .env:
# ==== OPTION 1: Claude.ai Web Client (Recommended for Projects) ====
# Get this from your browser's DevTools (Network tab -> Cookie header)
CLAUDE_COOKIE=sessionKey=sk-ant-sid01-xxx...
# Optional: Start in a specific conversation
CLAUDE_CONVERSATION_ID=your-conversation-uuid
# ==== OPTION 2: Official Anthropic API ====
ANTHROPIC_API_KEY=sk-ant-api03-xxx
CLAUDE_PROJECT_ID=your-project-uuid-here
# ==== Server Configuration (Optional) ====
FLASK_ENV=development
FLASK_DEBUG=True
HOST=127.0.0.1
PORT=5000
# Optional - Upload Limits (can also set in project_config.yaml)
MAX_FILE_SIZE=10485760 # 10MB in bytesGetting Your Claude Cookie (for Web Client):
- Open claude.ai and log in
- Open DevTools (F12 or Cmd+Option+I)
- Go to Network tab
- Click any request to claude.ai
- Find the
Cookieheader in Request Headers - Copy the entire cookie string (starts with
sessionKey=)
Getting Your Claude Project UUID (for API):
- Open ANY Claude Project in Claude.ai
- Look at the URL:
https://claude.ai/project/{PROJECT_UUID} - Copy the UUID and add to
.env
The interface will work with ANY Claude Project - the web client gives you access to all your projects through the Settings modal.
# Start development server
python app.py
# Or use Flask CLI
flask run
# Access at http://127.0.0.1:5000# Install new package
pip install package_name
# Update requirements.txt
pip freeze > requirements.txt
# Install from requirements
pip install -r requirements.txt# Format code with black
pip install black
black .
# Lint with flake8
pip install flake8
flake8 app.py utils/
# Type checking with mypy
pip install mypy
mypy app.py utils/Analyze positioning clarity using Claude Project.
Request:
{
"prompt_id": "full_analysis",
"input": "Optional URL or concept",
"files": ["/path/to/file1.pdf", "/path/to/file2.docx"],
"session_id": "session_abc123"
}Response:
{
"response": "## Concept Clarity Score: 62/100\n...",
"session_id": "session_abc123",
"analysis_time": 2.34
}Upload file for analysis.
Request: multipart/form-data with file field
Response:
{
"filepath": "static/uploads/pitch_deck.pdf",
"filename": "pitch_deck.pdf",
"size": 245678
}Get available preconfigured prompts.
Response:
{
"prompts": [
{
"id": "full_analysis",
"label": "Full Positioning Clarity Analysis",
"requires_files": true,
"min_files": 2
}
]
}Retrieve conversation history for a session.
Response:
{
"session_id": "session_abc123",
"messages": [
{"role": "user", "content": "..."},
{"role": "assistant", "content": "..."}
]
}The prompt system is completely configurable via project_config.yaml. Below are example templates you can customize for your specific Claude Project.
These are included as examples - edit project_config.yaml to customize:
prompts:
- id: "general_chat"
label: "General Chat"
template: "{user_input}"
requires_files: false
requires_input: true
- id: "document_analysis"
label: "Analyze Document"
template: "Please analyze this document: {user_input}"
requires_files: true
min_files: 1
- id: "compare_documents"
label: "Compare Documents"
template: "Compare these documents and highlight key differences"
requires_files: true
min_files: 2
- id: "url_analysis"
label: "Analyze Website"
template: "Analyze this website: {url}"
requires_url: trueUse these in your prompt templates:
{user_input}- Text from input field{url}- URL from input field{concept}- Specific concept to analyze{files}- Automatically includes uploaded files
prompt:
id: "unique_id" # Unique identifier
label: "Display Name" # Shown in dropdown
template: "Prompt text..." # Sent to Claude
requires_files: true/false # Requires file upload
min_files: 2 # Minimum files needed
requires_url: true/false # Requires URL input
requires_input: true/false # Requires text input
placeholder: "Hint text..." # Input field placeholder
description: "What this does" # Tooltip text (optional)@app.route('/api/endpoint', methods=['POST'])
def endpoint_name():
"""
Endpoint description.
Returns:
JSON response with success/error
"""
# 1. Validate request
data = request.json
if not data:
return jsonify({'error': 'Invalid request'}), 400
# 2. Process data
result = process_data(data)
# 3. Return response
return jsonify({
'success': True,
'data': result
})from functools import wraps
def handle_errors(f):
@wraps(f)
def decorated_function(*args, **kwargs):
try:
return f(*args, **kwargs)
except ValueError as e:
return jsonify({'error': str(e)}), 400
except Exception as e:
app.logger.error(f'Error in {f.__name__}: {str(e)}')
return jsonify({'error': 'Internal server error'}), 500
return decorated_function
@app.route('/api/analyze', methods=['POST'])
@handle_errors
def analyze():
# Your code here
passclass APIClient {
constructor(baseURL = '') {
this.baseURL = baseURL;
}
async post(endpoint, data) {
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
}
}class ChatComponent {
constructor(elementId) {
this.element = document.getElementById(elementId);
this.state = {
messages: [],
isLoading: false
};
this.init();
}
init() {
// Bind event listeners
this.bindEvents();
// Initialize UI
this.render();
}
bindEvents() {
// Event listener setup
}
render() {
// Update DOM
}
}| Extension | Library | Notes |
|---|---|---|
.pdf |
PyPDF2 | Text extraction from PDF documents |
.docx |
python-docx | Word document processing |
.txt |
Native Python | Plain text files |
.md |
Native Python | Markdown files |
Edit utils/file_processor.py:
class FileProcessor:
SUPPORTED_EXTENSIONS = {
'pdf': 'read_pdf',
'docx': 'read_docx',
'txt': 'read_text',
'md': 'read_text',
'pptx': 'read_pptx' # Add new type
}
def read_pptx(self, filepath):
"""Extract text from PowerPoint"""
from pptx import Presentation
prs = Presentation(filepath)
text = []
for slide in prs.slides:
for shape in slide.shapes:
if hasattr(shape, "text"):
text.append(shape.text)
return '\n'.join(text)# Imports: stdlib, third-party, local
import os
from typing import Dict, List
from flask import Flask
from anthropic import Anthropic
from utils.prompts import get_prompts
# Constants at module level
MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB
# Class names: PascalCase
class ClaudeClient:
"""Handles communication with Claude API"""
def __init__(self, api_key: str):
self.client = Anthropic(api_key=api_key)
# Method names: snake_case
def send_message(self, message: str, files: List[str] = None) -> str:
"""
Send message to Claude.
Args:
message: User message text
files: Optional list of file paths
Returns:
Claude's response text
"""
# Implementation
pass// Use const/let, never var
const API_BASE_URL = '/api';
// Arrow functions for callbacks
const handleClick = () => {
console.log('clicked');
};
// Async/await for promises
async function fetchData() {
try {
const response = await fetch(url);
const data = await response.json();
return data;
} catch (error) {
console.error('Fetch error:', error);
}
}
// Template literals for strings
const message = `Hello, ${name}!`;
// Destructuring
const { data, error } = await apiCall();<!-- Semantic HTML5 -->
<main class="container mx-auto">
<section class="analysis-section">
<header>
<h2>Analysis Results</h2>
</header>
<article class="result-card">
<!-- Content -->
</article>
</section>
</main>/* Use Tailwind utilities first */
.custom-component {
@apply bg-white rounded-lg shadow-lg p-6;
}
/* Custom CSS only when necessary */
.gradient-text {
background: linear-gradient(to right, #3b82f6, #8b5cf6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}# Install pytest
pip install pytest pytest-flask
# Run tests
pytest
# Run with coverage
pytest --cov=utils --cov=appExample test:
# tests/test_file_processor.py
import pytest
from utils.file_processor import FileProcessor
def test_read_text_file():
processor = FileProcessor()
content = processor.read_text('test_files/sample.txt')
assert len(content) > 0
assert isinstance(content, str)# tests/test_api.py
def test_analyze_endpoint(client):
response = client.post('/api/analyze', json={
'prompt_id': 'quick_scan',
'files': ['test_files/doc1.pdf', 'test_files/doc2.pdf']
})
assert response.status_code == 200
data = response.json
assert 'response' in data
assert 'session_id' in data# Run on localhost only
python app.py
# Access: http://127.0.0.1:5000For sharing with team:
# app.py production config
if __name__ == '__main__':
# Use production WSGI server
from waitress import serve
serve(app, host='0.0.0.0', port=5000)# Install production server
pip install waitress
# Run production
python app.pySecurity checklist for production:
- Use HTTPS (nginx reverse proxy)
- Add authentication (Flask-Login)
- Rate limiting (Flask-Limiter)
- Secure file upload validation
- Environment variable protection
- CORS configuration
- Session management (Flask-Session)
Issue: ModuleNotFoundError: No module named 'anthropic'
# Solution: Activate virtual environment
source venv/bin/activate
pip install -r requirements.txtIssue: anthropic.APIError: invalid_api_key
# Solution: Check .env file
cat .env # Verify ANTHROPIC_API_KEY is correctIssue: File upload fails with large PDFs
# Solution: Increase max file size in config.py
MAX_FILE_SIZE = 20 * 1024 * 1024 # 20MBIssue: URL fetching returns empty content
# Solution: Add user agent to requests
headers = {'User-Agent': 'Mozilla/5.0'}
response = requests.get(url, headers=headers)| File | Purpose | Customization |
|---|---|---|
project_config.yaml |
EDIT THIS - Project-specific settings | Prompts, file types, UI, features |
custom_prompts.yaml |
CREATE THIS - Your custom templates | Personal templates (gitignored) |
.env |
EDIT THIS - API keys/cookies | Your credentials |
app.py |
Flask server, route definitions | Usually no changes needed |
config.py |
Environment loading | Usually no changes needed |
utils/claude_client.py |
Official Anthropic API wrapper | Works with any project |
utils/claude_web_client.py |
Claude.ai direct web client | Cookie-based auth for Projects |
utils/tool_handler.py |
Tool execution handler | For web client tool calls |
utils/file_processor.py |
File content extraction | Add custom file types here |
utils/prompt_templates.py |
20+ built-in templates | Add default templates here |
utils/prompt_compiler.py |
Template variable handling | URL sanitization, compilation |
static/js/app.js |
Frontend chat logic | ChatInterface, TemplateSettings |
static/js/prompt-builder.js |
Template UI + Project Manager | PromptBuilder, ProjectManager |
templates/index.html |
Main UI template | Customize branding/layout |
Recommended features to add to this generalized interface:
-
Multiple Project Profiles - Switch between Claude Projects
- Save multiple
project_config.yamlfiles - Project switcher in UI
- Remember last used project
- Save multiple
-
Session Persistence - SQLite database for conversation history
- Schema: sessions, messages, analyses tables
- History browsing per project
- Search across conversations
-
Project Template Library - Pre-built configs for common use cases
- Code review template
- Document analysis template
- Research assistant template
- Content creation template
- One-click project setup
-
Export Functionality - Download conversations and results
- PDF generation for reports
- Markdown export for documentation
- JSON export for data analysis
- Share conversation links
-
Advanced File Handling
- Drag-and-drop file upload
- File preview before sending
- Support for more file types (PPTX, XLSX, images)
- Batch file processing
-
UI Enhancements
- Dark mode toggle
- Custom CSS themes per project
- Conversation branching
- Response streaming (real-time)
- Message editing/regeneration
-
Integration Features
- Google Drive file picker
- Dropbox integration
- Slack notifications
- Webhook support for automation
- Flask Documentation
- Anthropic Python SDK
- Tailwind CSS
- PyPDF2 Documentation
- python-docx Documentation
- Concept Clarity System - Parent project documentation
# Daily workflow
source venv/bin/activate # Activate environment
python app.py # Start server
# Open: http://127.0.0.1:5000
# Add dependency
pip install package_name
pip freeze > requirements.txt
# Format code
black .
flake8 .
# Run tests
pytest
# Deactivate when done
deactivateEstimated costs vary by project and usage:
- Simple chat (no files): ~$0.01-0.05
- Document analysis (1-2 docs): ~$0.10-0.20
- Multi-document analysis (3+ docs): ~$0.20-0.40
- Complex analysis with context: ~$0.30-0.60
Factors affecting cost:
- Document length and complexity
- Number of files processed
- Conversation history length
- Project knowledge base size
Monthly estimates depend on usage:
- Light usage (10-20 interactions): $2-5
- Moderate usage (50-100 interactions): $10-20
- Heavy usage (200+ interactions): $30-60
Monitor usage in Anthropic Console: https://console.anthropic.com/
Cost optimization tips:
- Clear conversation history when starting new topics
- Use smaller context windows when possible
- Process documents in batches
- Limit file sizes
- Flask - Web framework
- Anthropic Python SDK - Official Claude API
- curl_cffi - HTTP client with browser impersonation
- BeautifulSoup4 - HTML parsing
- PyPDF2 - PDF text extraction
- python-docx - Word document processing
- Tailwind CSS - Utility-first CSS framework
- Claude-API by KoushikNavuluri - Inspired the approach for direct Claude.ai web access using cookie authentication
- Claude Code - AI-assisted development
Project Status: Development Primary Use: Local MacBook - works with ANY Claude Project Tech Stack: Python Flask + Anthropic Claude (API + Web Client) Goal: Universal chat interface for Claude Projects with configuration-driven customization
Note: This is an unofficial tool and is not affiliated with Anthropic. Use responsibly and in accordance with Anthropic's terms of service.