import { type MouseEvent as ReactMouseEvent, type ReactElement, useEffect, useRef, useState } from 'react' import { IconArrowUpRight, IconCheck, IconCopy, IconFolderOpen, IconMessageChatbot, IconX } from '@tabler/icons-react' import claudeIcon from '@/client/assets/claude.svg' import floppyDisk from '@/client/assets/floppy-disk.webp' import hermesIcon from '@/client/assets/hermes.png' import openaiIcon from '@/client/assets/openai.svg' import openclawIcon from '@/client/assets/openclaw.svg' import { Button, buttonVariants } from '@/client/components/ui/button' import { Dialog, DialogClose, DialogContent, DialogDescription, DialogTitle, DialogTrigger } from '@/client/components/ui/dialog' import { useAppConfig } from '@/client/api/app-config' // The canonical setup prompt from moi.computer — pasted into any agent, it // fetches INSTALL.md and walks itself through the install. const AGENT_COMMAND = 'Set up the moi workspace for this project. Fetch https://moi.computer/INSTALL.md, and follow the steps.' type DemoDialogProps = { // Trigger-owned (uncontrolled) or controlled via open/onOpenChange — the // create-workspace buttons use the former, programmatic opens the latter. trigger?: ReactElement open?: boolean onOpenChange?: (open: boolean) => void } // Shown in the cloud demo wherever a workspace would be created: the demo is // limited to its built-in workspaces, and the way out is installing moi. export function DemoDialog({ trigger, open, onOpenChange }: DemoDialogProps) { return ( {trigger && } ) } type FloppyArtworkProps = { demoInstallUrl: string } const FLOPPY_POINTER_TRAVEL = 2 function FloppyArtwork({ demoInstallUrl }: FloppyArtworkProps) { const floppyRef = useRef(null) const moveFloppyOppositePointer = (event: ReactMouseEvent) => { if (!floppyRef.current) return const bounds = event.currentTarget.getBoundingClientRect() const x = (event.clientX - bounds.left) / bounds.width - 0.5 const y = (event.clientY - bounds.top) / bounds.height - 0.5 floppyRef.current.style.setProperty('--floppy-x', `${x * -2 * FLOPPY_POINTER_TRAVEL}px`) floppyRef.current.style.setProperty('--floppy-y', `${y * -2 * FLOPPY_POINTER_TRAVEL}px`) } const resetFloppyPosition = () => { floppyRef.current?.style.removeProperty('--floppy-x') floppyRef.current?.style.removeProperty('--floppy-y') } return (
About moi
) } function useCopyCommand() { const [copied, setCopied] = useState(false) useEffect(() => { if (!copied) return const t = setTimeout(() => setCopied(false), 1500) return () => clearTimeout(t) }, [copied]) const copy = () => { navigator.clipboard ?.writeText(AGENT_COMMAND) .then(() => setCopied(true)) .catch(() => {}) } return { copied, copy } } function DemoDialogContent() { const { demoInstallUrl } = useAppConfig() const { copied, copy } = useCopyCommand() return (
{/* Film grain keeps the illustration gradient from banding. */}
Unlock all features This is a demo version with sample workspaces. Install moi locally and connect to your agent.
  • Connect your own data sources and work on existing projects
  • Build with Claude Code, Codex, Hermes, OpenClaw, and more

Give this prompt to your agent:

{AGENT_COMMAND}
} /> ) }