Tags: sisimomo/aivm
Tags
feat: structured mounts with remapped guest paths and Docker bootstra… …p promotion (#37) Replace same-path-only mounts and agent `persist:` with a unified mount model using explicit `source` / `target` / `mode` entries. Agent state now binds to the guest paths tools expect (e.g. `~/.claude/projects`), user `vm.mounts` can remap host trees to different guest locations (e.g. `~/dev` → `/work`), and `aivm ssh` / agent launch translate host CWD through configured mounts. On Docker, bootstrap with VM-only mounts so agent installers can write scratch paths under `~/.claude`, then promote the container to full runtime mounts (agent + T3) via base-image finalize. Lima keeps single-phase mounts and applies remapped bind mounts through the Lima template. Encapsulate backend-specific mount behavior behind `vm.VM` lifecycle hooks (`UsesBootstrapOnlyMounts`, `PrepareHostMountDir`, `FinalizeAfterBootstrap`) so lifecycle code stays backend-agnostic. Move `DefaultUserHome` into the vm package and install agents through `mise-<tool>` plugins. BREAKING CHANGE: Alpha hard cut — string `vm.mounts` (`~/path:rw`) and agent `persist:` are removed. Use structured mounts instead: ```yaml vm: mounts: - source: "~/dev" target: "/work" mode: rw # agents: mounts in defaults.yaml / agents.define mounts: - source: "{{ .state_dir }}/.claude/projects" target: "~/.claude/projects" mode: rw ``` On Lima/macOS, same-path mounts that must appear at the host absolute path inside the VM should use `{{ .host_home }}` in `target`.
feat(agent): add agent subcommand for external tool integration (#29) Introduce `aivm agent -- <args>` to run the configured agent CLI in the VM with forwarded arguments, without interactive launch_args. Split agent config into cli_command and launch_args and reject unknown keys under agents.define. Replace the debug flag with structured log levels (debug/info/warn/error) via --log-level, AIVM_LOG_LEVEL, and log_level in config. At error level, suppress bootstrap noise and SSH teardown for cleaner Cursor/OpenCode integration. Add VM RunStream, quiet stderr filtering, and shared prepareAgentSession for Launch and AgentRun. Default non-interactive lifecycle prompts to keep the VM. Co-authored-by: Cursor <cursoragent@cursor.com>
feat(agent): add Cursor Agent as a built-in provider (#26) Add `cursor` as a fourth built-in AI agent alongside claude, copilot, and opencode. Installs via `curl https://cursor.com/install -fsS | bash`, persists state to `~/.aivm/.cursor/`, and launches with `agent --yolo`. - Register cursor in internal/agent/defaults.yaml with system dependency - Handle cursor's `agent` binary name in test framework and CLI descriptions - Add bootstrap test (TestAgent_Cursor) and unit test coverage - Update README and aivm.example.yaml with cursor configuration docs
fix(agent): replace claude-code flag in opencode launch_command, add … …regression test (#24) Remove --dangerously-skip-permissions from opencode launch_command (a Claude Code flag that opencode does not recognise) and instead configure permissions via the setup script. Add AssertLaunchStartsTUI harness method and regression test to verify the TUI actually starts.
feat(integration): replace cocoindex-code MCP with plugin-level skill… … install (#22) cocoindex-code now ships a SKILL.md (skills/ccc/SKILL.md) that teaches agents to invoke `ccc` as a CLI tool directly, replacing the previous MCP server approach. Remove the three per-agent MCP integrations: - cocoindex-code:claude — `claude mcp add cocoindex-code -- ccc mcp` - cocoindex-code:copilot — jq-based write to ~/.copilot/mcp-config.json - cocoindex-code:opencode — jq-based write to ~/.config/opencode/opencode.json Instead, add `npx skills@latest add cocoindex-io/cocoindex-code --global --all` to the cocoindex-code plugin setup (with mise-node as a new dependency). The skill is installed once when `ccc` is bootstrapped, scoping naturally to whichever agent directories already exist in the VM. Update bootstrap tests: remove TestIntegration_CocoindexCode_{Claude, Copilot,OpenCode}; add TestPlugin_CocoindexCode_SkillInstall which pre-creates a copilot dir and asserts the skill directory is created as part of the plugin install. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
feat!: replace rebuild-image with recreate; remove base image concept (… …#21) * fix(ci): add aivm-test to PATH Ensure e2e and bootstrap jobs can find the installed aivm-test binary after make install-test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat!: replace rebuild-image with recreate; remove base image concept BREAKING CHANGE: removes `rebuild-image` command and `base_image_rebuild_prompt_after` config The base image mechanism (save/restore VM snapshots for faster bootstrap) adds complexity without proportionate value. Remove it entirely and replace the `rebuild-image` CLI command with a simpler `recreate` command that always performs a clean destroy-and-bootstrap. - Delete vm/image.go (ImageManager, base image save/restore/snapshot logic) - Remove base-image methods from colima.go, docker.go and the vm.VM interface - Add vm/vmstate.go for lightweight VM creation-timestamp helpers - Replace cli/rebuild_image.go with cli/recreate.go (new `aivm recreate` subcommand) - Simplify lifecycle/service.go: fresh VMs always do a full bootstrap - Remove base_image_rebuild_prompt_after config; VM age check now uses the existing recreate_prompt_after threshold, reading the timestamp file directly - Drop base-image lines from `aivm status` output - Remove rebuild-image and vm_creation e2e tests; add recreate e2e tests - Remove base-image helpers from test framework Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
fix(lifecycle): only bring up compose services when VM starts (#17) Condition the `Compose.Up` call on the `needsStart` flag within the `Start` method. This ensures that Docker Compose services are not re-initialized if the VM is already running, preventing unnecessary overhead and potential state conflicts during service checks.
fix(lifecycle): use state file to detect T3 Code status (#13) * fix(lifecycle): use state file to detect T3 Code status Update `Status` to check for the `t3code-url` state file instead of in-memory state, ensuring accurate reporting across subprocesses. * Use `os.Stat` on the state file to determine if T3 Code is running. * Add E2E test to verify the running icon in status output.
fix: normalize nil and empty values in config hashing (#12) * fix: normalize nil and empty values in config hashing Normalize nil slices and maps to empty ones in `ComputeConfigHash` to prevent false-positive change detections caused by inconsistent zero-value deserialization. * Export `ComputeConfigHash` for testing * Add regression tests for hash stability and value normalization
PreviousNext