it's alive
This commit is contained in:
parent
994c26647d
commit
606b440891
|
|
@ -117,6 +117,14 @@ program
|
||||||
|
|
||||||
const vmCmd = program.command("vm").description("Manage the sandlot VM")
|
const vmCmd = program.command("vm").description("Manage the sandlot VM")
|
||||||
|
|
||||||
|
vmCmd
|
||||||
|
.command("shell")
|
||||||
|
.description("Open a shell in the VM")
|
||||||
|
.action(async () => {
|
||||||
|
await vm.ensure()
|
||||||
|
await vm.shell()
|
||||||
|
})
|
||||||
|
|
||||||
vmCmd
|
vmCmd
|
||||||
.command("status")
|
.command("status")
|
||||||
.description("Show VM status")
|
.description("Show VM status")
|
||||||
|
|
|
||||||
30
src/vm.ts
30
src/vm.ts
|
|
@ -19,7 +19,10 @@ export async function ensure(): Promise<void> {
|
||||||
await $`limactl start ${VM_NAME}`.quiet()
|
await $`limactl start ${VM_NAME}`.quiet()
|
||||||
|
|
||||||
// Provision
|
// Provision
|
||||||
await $`limactl shell ${VM_NAME} -- sudo bash -c "curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && apt-get install -y nodejs && npm install -g @anthropic-ai/claude-code"`.quiet()
|
await $`limactl shell ${VM_NAME} -- bash -c "curl -fsSL https://claude.ai/install.sh | bash"`.quiet()
|
||||||
|
|
||||||
|
// Replace ~/.claude and ~/.claude.json with symlinks to host credentials
|
||||||
|
await $`limactl shell ${VM_NAME} -- bash -c "rm -rf ~/.claude ~/.claude.json && ln -sf ${home}/.claude ~/.claude && ln -sf ${home}/.claude.json ~/.claude.json"`.quiet()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check VM status. */
|
/** Check VM status. */
|
||||||
|
|
@ -41,10 +44,33 @@ export async function status(): Promise<"running" | "stopped" | "missing"> {
|
||||||
return "missing"
|
return "missing"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Load env vars from ~/.env */
|
||||||
|
async function loadEnv(): Promise<Record<string, string>> {
|
||||||
|
const envFile = Bun.file(`${homedir()}/.env`)
|
||||||
|
if (!(await envFile.exists())) return {}
|
||||||
|
const vars: Record<string, string> = {}
|
||||||
|
for (const line of (await envFile.text()).split("\n")) {
|
||||||
|
const match = line.match(/^([A-Z_]+)=(.+)$/)
|
||||||
|
if (match) vars[match[1]] = match[2]
|
||||||
|
}
|
||||||
|
return vars
|
||||||
|
}
|
||||||
|
|
||||||
/** Launch claude in the VM at the given workdir. */
|
/** Launch claude in the VM at the given workdir. */
|
||||||
export async function claude(workdir: string): Promise<void> {
|
export async function claude(workdir: string): Promise<void> {
|
||||||
|
const env = await loadEnv()
|
||||||
|
const envArgs = Object.entries(env).map(([k, v]) => `${k}=${v}`)
|
||||||
const proc = Bun.spawn(
|
const proc = Bun.spawn(
|
||||||
["limactl", "shell", `--workdir=${workdir}`, VM_NAME, "claude", "--dangerously-skip-permissions"],
|
["limactl", "shell", `--workdir=${workdir}`, VM_NAME, "env", ...envArgs, "claude", "--dangerously-skip-permissions"],
|
||||||
|
{ stdin: "inherit", stdout: "inherit", stderr: "inherit" },
|
||||||
|
)
|
||||||
|
await proc.exited
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Open an interactive shell in the VM. */
|
||||||
|
export async function shell(): Promise<void> {
|
||||||
|
const proc = Bun.spawn(
|
||||||
|
["limactl", "shell", VM_NAME],
|
||||||
{ stdin: "inherit", stdout: "inherit", stderr: "inherit" },
|
{ stdin: "inherit", stdout: "inherit", stderr: "inherit" },
|
||||||
)
|
)
|
||||||
await proc.exited
|
await proc.exited
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user