Files
fireclaw/src/rootfs.ts
ansible ff694d12f6 Initial commit — fireclaw multi-agent system
Firecracker microVM-based multi-agent system with IRC orchestration and local LLMs.

Features:
- Ephemeral command runner with VM snapshots (~1.1s)
- Multi-agent orchestration via overseer IRC bot
- 5 agent templates (worker, coder, researcher, quick, creative)
- Tool access (shell + podman containers inside VMs)
- Persistent workspace + memory system (MEMORY.md pattern)
- Agent hot-reload (model/persona swap via SSH + SIGHUP)
- Non-root agents, graceful shutdown, crash recovery
- Agent-to-agent communication via IRC
- DM support, /invite support
- Systemd service, 20 regression tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:28:29 +00:00

99 lines
2.2 KiB
TypeScript

import { execFileSync } from "node:child_process";
import {
existsSync,
copyFileSync,
mkdirSync,
unlinkSync,
} from "node:fs";
import { join } from "node:path";
import { randomBytes } from "node:crypto";
import { CONFIG } from "./config.js";
export function ensureBaseImage() {
if (!existsSync(CONFIG.baseRootfs)) {
throw new Error(
`Base rootfs not found at ${CONFIG.baseRootfs}. Run 'fireclaw setup' first.`
);
}
if (!existsSync(CONFIG.kernelPath)) {
throw new Error(
`Kernel not found at ${CONFIG.kernelPath}. Run 'fireclaw setup' first.`
);
}
}
export function ensureSshKeypair() {
if (!existsSync(CONFIG.sshKeyPath)) {
execFileSync("ssh-keygen", [
"-t",
"ed25519",
"-f",
CONFIG.sshKeyPath,
"-N",
"",
"-C",
"fireclaw",
]);
}
}
export function createRunCopy(vmId: string): string {
mkdirSync(CONFIG.runsDir, { recursive: true });
const dest = join(CONFIG.runsDir, `${vmId}.ext4`);
copyFileSync(CONFIG.baseRootfs, dest);
return dest;
}
export function injectSshKey(rootfsPath: string) {
const mountPoint = `/tmp/fireclaw-mount-${randomBytes(4).toString("hex")}`;
mkdirSync(mountPoint, { recursive: true });
try {
execFileSync("sudo", ["mount", "-o", "loop", rootfsPath, mountPoint], {
stdio: "pipe",
});
execFileSync("sudo", ["mkdir", "-p", join(mountPoint, "root/.ssh")], {
stdio: "pipe",
});
execFileSync(
"sudo",
[
"cp",
CONFIG.sshPubKeyPath,
join(mountPoint, "root/.ssh/authorized_keys"),
],
{ stdio: "pipe" }
);
execFileSync(
"sudo",
["chmod", "600", join(mountPoint, "root/.ssh/authorized_keys")],
{ stdio: "pipe" }
);
execFileSync(
"sudo",
["chmod", "700", join(mountPoint, "root/.ssh")],
{ stdio: "pipe" }
);
} finally {
try {
execFileSync("sudo", ["umount", mountPoint], { stdio: "pipe" });
} catch {
// Best effort
}
try {
execFileSync("rmdir", [mountPoint], { stdio: "pipe" });
} catch {
// Best effort
}
}
}
export function deleteRunCopy(rootfsPath: string) {
try {
unlinkSync(rootfsPath);
} catch {
// Already gone
}
}