import { useState, useEffect } from "react"; import { useAuth } from "../contexts/AuthContext"; import { useNavigate } from "react-router"; import { Masthead } from "../components/Masthead"; import { listDaemons, restartDaemon, type Daemon, type DaemonListResponse, } from "../lib/api"; // ============================================================================= // Section Header Component // ============================================================================= function SectionHeader({ children }: { children: React.ReactNode }) { return (

{children}

); } // ============================================================================= // Alert Component // ============================================================================= function ErrorAlert({ children }: { children: React.ReactNode }) { return (
{children}
); } // ============================================================================= // Daemons Page // ============================================================================= export default function DaemonsPage() { const { isAuthenticated, isAuthConfigured } = useAuth(); const navigate = useNavigate(); // Daemon state const [daemons, setDaemons] = useState([]); const [daemonsLoading, setDaemonsLoading] = useState(true); const [daemonsError, setDaemonsError] = useState(null); const [restartingDaemonId, setRestartingDaemonId] = useState(null); const [restartConfirmDaemonId, setRestartConfirmDaemonId] = useState(null); // Redirect if not authenticated useEffect(() => { if (isAuthConfigured && !isAuthenticated) { navigate("/login"); } }, [isAuthConfigured, isAuthenticated, navigate]); const loadDaemons = async () => { try { setDaemonsError(null); const response: DaemonListResponse = await listDaemons(); setDaemons(response.daemons); } catch (err) { setDaemonsError(err instanceof Error ? err.message : "Failed to load daemons"); } finally { setDaemonsLoading(false); } }; const handleRestartDaemon = async (id: string) => { try { setRestartingDaemonId(id); setDaemonsError(null); await restartDaemon(id); // Daemon will restart, so refresh the list after a short delay setTimeout(() => { loadDaemons(); }, 2000); } catch (err) { setDaemonsError(err instanceof Error ? err.message : "Failed to restart daemon"); } finally { setRestartingDaemonId(null); setRestartConfirmDaemonId(null); } }; // Static platform data for download links const downloadPlatforms = [ { key: "linux-x86_64", label: "Linux (Intel/AMD)", filename: "makima-vX.X.X-linux-x86_64.tar.gz" }, { key: "linux-arm64", label: "Linux (ARM64)", filename: "makima-vX.X.X-linux-arm64.tar.gz" }, { key: "macos-x86_64", label: "macOS (Intel)", filename: "makima-vX.X.X-macos-x86_64.tar.gz" }, { key: "macos-arm64", label: "macOS (Apple Silicon)", filename: "makima-vX.X.X-macos-arm64.tar.gz" }, ]; // Initial load useEffect(() => { loadDaemons(); }, []); // Auto-refresh daemons every 30 seconds useEffect(() => { const interval = setInterval(() => { loadDaemons(); }, 30000); return () => clearInterval(interval); }, []); return (
{/* Page Header */}

Daemons

Daemons are worker processes that connect to Makima and execute tasks on your machines.

{/* Left Column */}
{/* Download Section */}
Download Daemon

Download the pre-compiled daemon binary for your platform. The daemon connects to the Makima server and executes tasks.

{downloadPlatforms.map((p) => ( {p.label} {p.filename} ))}

Quick Install

curl -fsSL https://raw.githubusercontent.com/soryu-co/makima/master/install.sh | bash
{/* Daemon Setup */}
Daemon Setup

Set your API key as an environment variable:

export MAKIMA_API_KEY="your-key"

Then run: makima-daemon

{/* Kubernetes Section */}
Run in Kubernetes

Deploy daemons as containers in Kubernetes for scalable task execution.

Pull Container Image

docker pull ghcr.io/soryu-co/makima-daemon:latest

Environment Variables

MAKIMA_API_KEY="your-key"
MAKIMA_SERVER_URL="https://your-server"
GITHUB_TOKEN="ghp_..." # optional, for repo access

Kubernetes manifests available at{" "} github.com/soryu-co/makima

{/* Right Column */}
{/* Connected Daemons */}

Connected Daemons

{daemons.length > 0 && ( ({daemons.filter(d => d.status === "connected").length} connected / {daemons.length} total) )}
{daemonsError && {daemonsError}} {daemonsLoading && daemons.length === 0 ? (

Loading...

) : daemons.length === 0 ? (

No daemons connected

Start a daemon to enable task execution

) : (
{daemons.map((daemon) => (
{daemon.hostname || "Unknown Host"}
{daemon.status}
Tasks {daemon.currentTaskCount} / {daemon.maxConcurrentTasks}
Connected {new Date(daemon.connectedAt).toLocaleString()}
{daemon.machineId && (
Machine {daemon.machineId.substring(0, 16)}...
)}
{/* Restart Section */} {daemon.status === "connected" && (
{restartConfirmDaemonId === daemon.id ? (
Restart daemon? Running tasks will be interrupted.
) : ( )}
)}
))}
)}
); }