React SDK
React hooks and components for Cmdop integration.
Setup
Wrap your app with CmdopProvider:
import { CmdopProvider } from '@cmdop/react';
function App() {
return (
<CmdopProvider apiKey={process.env.NEXT_PUBLIC_CMDOP_API_KEY}>
<YourApp />
</CmdopProvider>
);
}Hooks
useMachines
List all machines:
import { useMachines } from '@cmdop/react';
function MachineList() {
const { machines, loading, error, refetch } = useMachines();
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{machines.map((machine) => (
<li key={machine.id}>
{machine.name} - {machine.status}
</li>
))}
</ul>
);
}useMachine
Get single machine:
import { useMachine } from '@cmdop/react';
function MachineDetail({ id }: { id: string }) {
const { machine, loading, error } = useMachine(id);
if (loading) return <div>Loading...</div>;
if (!machine) return <div>Not found</div>;
return (
<div>
<h2>{machine.name}</h2>
<p>Status: {machine.status}</p>
<p>OS: {machine.os}</p>
</div>
);
}useCommand
Execute commands:
import { useCommand } from '@cmdop/react';
function CommandRunner({ machineId }: { machineId: string }) {
const { execute, result, loading, error } = useCommand(machineId);
const handleRun = async () => {
await execute('ls -la');
};
return (
<div>
<button onClick={handleRun} disabled={loading}>
Run Command
</button>
{result && (
<pre>{result.stdout}</pre>
)}
</div>
);
}useTerminal
Interactive terminal:
import { useTerminal } from '@cmdop/react';
function Terminal({ machineId }: { machineId: string }) {
const {
output,
send,
clear,
connected
} = useTerminal(machineId);
return (
<div>
<pre>{output}</pre>
<input
onKeyDown={(e) => {
if (e.key === 'Enter') {
send(e.currentTarget.value);
e.currentTarget.value = '';
}
}}
/>
</div>
);
}useFiles
File operations:
import { useFiles } from '@cmdop/react';
function FileExplorer({ machineId }: { machineId: string }) {
const {
files,
path,
navigate,
loading
} = useFiles(machineId, '/home');
return (
<div>
<p>Current: {path}</p>
<ul>
{files.map((file) => (
<li
key={file.name}
onClick={() => file.isDirectory && navigate(file.path)}
>
{file.isDirectory ? '📁' : '📄'} {file.name}
</li>
))}
</ul>
</div>
);
}useRealtime
Real-time subscriptions:
import { useRealtime } from '@cmdop/react';
function StatusMonitor({ machineId }: { machineId: string }) {
const { status, lastUpdate } = useRealtime(machineId);
return (
<div>
<p>Status: {status}</p>
<p>Updated: {lastUpdate?.toLocaleTimeString()}</p>
</div>
);
}Components
Terminal Component
Pre-built terminal component:
import { Terminal } from '@cmdop/react';
function App() {
return (
<Terminal
machineId="your-machine-id"
height={400}
theme="dark"
/>
);
}TypeScript
Full type support:
import { Machine, CommandResult } from '@cmdop/react';
function MachineCard({ machine }: { machine: Machine }) {
return <div>{machine.name}</div>;
}