"use client"; import { useState, useEffect } from "react"; interface Tab { id: string; name: string; icon: string; color: string; projectPath?: string; status?: "inactive" | "starting" | "active"; sessionKey?: string; } const TABS_STORAGE_KEY = "mc_claude_tabs"; export default function ClaudePage() { const [tabs, setTabs] = useState([ { id: "main", name: "Claude Code", icon: "🤖", color: "#ff6154", status: "inactive" }, ]); const [activeTab, setActiveTab] = useState("main"); const [showSettings, setShowSettings] = useState(false); const [apiKey, setApiKey] = useState(""); const [message, setMessage] = useState(""); useEffect(() => { const saved = localStorage.getItem(TABS_STORAGE_KEY); if (saved) { try { setTabs(JSON.parse(saved)); } catch (e) {} } const savedKey = localStorage.getItem("anthropic_api_key") || ""; setApiKey(savedKey); }, []); const saveTabs = (newTabs: Tab[]) => { localStorage.setItem(TABS_STORAGE_KEY, JSON.stringify(newTabs)); setTabs(newTabs); }; const spawnSession = async (tabId: string) => { const tab = tabs.find(t => t.id === tabId); if (!tab) return; // Update status to starting const newTabs = tabs.map(t => t.id === tabId ? { ...t, status: "starting" as const } : t ); saveTabs(newTabs); try { const response = await fetch("/api/claude/spawn", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ tabId, tabName: tab.name, apiKey }), }); const data = await response.json(); if (data.success) { // Update with session info const finalTabs = tabs.map(t => t.id === tabId ? { ...t, status: "active" as const, sessionKey: data.sessionKey } : t ); saveTabs(finalTabs); setMessage(`Session spawned! Ask Horus to connect.`); } else { setMessage(`Error: ${data.error}`); } } catch (e) { setMessage(`Connection failed. Try asking Horus directly.`); } }; const addTab = () => { const name = prompt("Project name:"); if (!name) return; const colors = ["#ff6154", "#3b82f6", "#22c55e", "#f59e0b", "#8b5cf6", "#ec4899"]; const newTab: Tab = { id: `tab-${Date.now()}`, name, icon: "📁", color: colors[Math.floor(Math.random() * colors.length)], status: "inactive", }; saveTabs([...tabs, newTab]); setActiveTab(newTab.id); }; const removeTab = (tabId: string) => { if (tabs.length <= 1) return; const newTabs = tabs.filter(t => t.id !== tabId); saveTabs(newTabs); if (activeTab === tabId) { setActiveTab(newTabs[0].id); } }; const activeTabData = tabs.find(t => t.id === activeTab); return (
{/* Header */}

🤖 Claude Code Sessions

Spawn coding agents powered by Claude

{/* Tabs Bar */}
{tabs.map((tab) => (
setActiveTab(tab.id)} className={` flex items-center gap-2 px-4 py-2 rounded-lg cursor-pointer transition-all text-sm font-medium whitespace-nowrap ${activeTab === tab.id ? "bg-slate-800 text-white border border-slate-600" : "bg-slate-800/50 text-slate-400 border border-transparent hover:bg-slate-800 hover:text-white" } `} > {tab.icon} {tab.name} {tab.status === "active" && ( )} {tab.status === "starting" && ( )} {tabs.length > 1 && ( )}
))}
{/* Content */}
{activeTabData?.status === "inactive" && ( <>
{activeTabData.icon}

{activeTabData.name}

Start a Claude Code session for this project

)} {activeTabData?.status === "starting" && ( <>

Starting Session...

Connecting to Claude Code

)} {activeTabData?.status === "active" && ( <>

Session Active!

Session ID: {activeTabData.sessionKey?.slice(0, 12)}...

💡 To use this session:

Ask Horus to connect to this session for coding tasks.

)} {message && (

{message}

)}
{/* Instructions */}
💡 Claude Code sessions run as separate agents. Ask Horus to delegate coding tasks to them.
{tabs.filter(t => t.status === "active").length > 0 && ( ● {tabs.filter(t => t.status === "active").length} active )}
{/* Settings Modal */} {showSettings && (

⚙️ Settings

setApiKey(e.target.value)} placeholder="sk-ant-..." className="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-white text-sm" />

Get key from console.anthropic.com

)}
); }