在 NixOS 上使用 microvm.nix 的编码代理虚拟机

Michael Stapelberg 工具

摘要

一篇技术指南,介绍如何在 NixOS 上使用 microvm.nix 创建临时虚拟机,以便在无法访问个人文件的情况下安全运行编码代理。

<p>我已经认识到,编码代理在处理计算机程序代码方面是有价值的工具,无论用途如何,例如了解程序架构、诊断错误或开发概念验证。根据使用场景,审查代理想要运行的每个命令会很快变得繁琐且耗时。为了在不审查的情况下安全运行编码代理,我想要一个虚拟机解决方案,使代理无法访问我的个人文件,并且如果代理被恶意软件入侵也无大碍:我只需丢弃虚拟机并重新开始。</p> <p>我不喜欢设置一个有状态虚拟机并在需要时重新安装(哎呀!),而是更喜欢临时虚拟机的模式,即除了显式与主机共享的内容外,磁盘上不保留任何东西。</p> <p><a href="https://github.com/microvm-nix/microvm.nix"><code>microvm.nix</code> 项目</a>使得在 NixOS 上创建此类虚拟机变得容易,本文展示了我是如何设置我的虚拟机的。</p> <h2 id="see-also">另请参阅</h2> <p>如果你以前没有听说过 NixOS,请查看 <a href="https://en.wikipedia.org/wiki/NixOS">NixOS 维基百科页面</a>和 <a href="https://nixos.org/">nixos.org</a>。我曾在 <a href="/talks/#2025">2025 年谈论过我为何转向 Nix</a>,并发布了一些<a href="/posts/tags/nix/">关于 Nix 的博客文章</a>。</p> <p>要了解 AI 代理的威胁模型,请阅读 <a href="https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/">Simon Willison 的《AI 代理的致命三重奏:私有数据、不可信内容和外部通信》(2025 年 6 月)</a>。本文处理威胁模型的方法是删除等式中的“私有数据”部分。</p> <p>如果你想了解沙盒的整个领域,请查看 <a href="https://www.luiscardoso.dev/blog/sandboxes-for-ai">Luis Cardoso 的《AI 沙盒现场指南》(2026 年 1 月)</a>。我不会在本文中比较不同的解决方案,只会向你展示一条可能路径。</p> <p>最后,也许你不想自己构建/运行沙盒基础设施。好消息是:沙盒是一个热门话题,许多商业产品不断涌现以满足这一需求。例如,David Crawshaw 和 Josh Bleecher Snyder(我都从 Go 社区了解他们)最近推出了 <a href="https://blog.exe.dev/meet-exe.dev">exe.dev</a>,一个对代理友好的虚拟机托管服务。另一个例子是 <a href="https://fly.io/blog/code-and-let-live/">Fly.io,他们推出了 Sprites</a>。</p> <h2 id="setting-up-microvmnix">设置 microvm.nix</h2> <p>让我们直接开始吧!接下来的部分将引导你了解我是如何配置的。</p> <h3 id="step-1-network-prep">步骤 1:网络准备</h3> <p>首先,我创建了一个新的 <code>microbr</code> 桥接,它使用 <code>192.168.33.1/24</code> 作为 IP 地址范围,并通过 <code>eno1</code> 网络接口进行 NAT。所有 <code>microvm*</code> 接口都将添加到该桥接中:</p> <div class="highlight"><pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>systemd<span style="color:#666">.</span>network<span style="color:#666">.</span>netdevs<span style="color:#666">.</span><span style="color:#4070a0">&#34;20-microbr&#34;</span><span style="color:#666">.</span>netdevConfig <span style="color:#666">=</span> { </span></span><span style="display:flex;"><span> Kind <span style="color:#666">=</span> <span style="color:#4070a0">&#34;bridge&#34;</span>; </span></span><span style="display:flex;"><span> Name <span style="color:#666">=</span> <span style="color:#4070a0">&#34;microbr&#34;</span>; </span></span><span style="display:flex;"><span>}; </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span>systemd<span style="color:#666">.</span>network<span style="color:#666">.</span>networks<span style="color:#666">.</span><span style="color:#4070a0">&#34;20-microbr&#34;</span> <span style="color:#666">=</span> { </span></span><span style="display:flex;"><span> matchConfig<span style="color:#666">.</span>Name <span style="color:#666">=</span> <span style="color:#4070a0">&#34;microbr&#34;</span>; </span></span><span style="display:flex;"><span> addresses <span style="color:#666">=</span> [ { Address <span style="color:#666">=</span> <span style="color:#4070a0">&#34;192.168.83.1/24&#34;</span>; } ]; </span></span><span style="display:flex;"><span> networkConfig <span style="color:#666">=</span> { </span></span><span style="display:flex;"><span> ConfigureWithoutCarrier <span style="color:#666">=</span> <span style="color:#60add5">true</span>; </span></span><span style="display:flex;"><span> }; </span></span><span style="display:flex;"><span>}; </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span>systemd<span style="color:#666">.</span>network<span style="color:#666">.</span>networks<span style="color:#666">.</span><span style="color:#4070a0">&#34;21-microvm-tap&#34;</span> <span style="color:#666">=</span> { </span></span><span style="display:flex;"><span> matchConfig<span style="color:#666">.</span>Name <span style="color:#666">=</span> <span style="color:#4070a0">&#34;microvm*&#34;</span>; </span></span><span style="display:flex;"><span> networkConfig<span style="color:#666">.</span>Bridge <span style="color:#666">=</span> <span style="color:#4070a0">&#34;microbr&#34;</span>; </span></span><span style="display:flex;"><span>}; </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span>networking<span style="color:#666">.</span>nat <span style="color:#666">=</span> { </span></span><span style="display:flex;"><span> enable <span style="color:#666">=</span> <span style="color:#60add5">true</span>; </span></span><span style="display:flex;"><span> internalInterfaces <span style="color:#666">=</span> [ <span style="color:#4070a0">&#34;microbr&#34;</span> ]; </span></span><span style="display:flex;"><span> externalInterface <span style="color:#666">=</span> <span style="color:#4070a0">&#34;eno1&#34;</span>; </span></span><span style="display:flex;"><span>}; </span></span></code></pre></div><h3 id="step-2-flakenix">步骤 2:<code>flake.nix</code></h3> <p>然后,我将 <code>microvm</code> 模块作为新输入添加到我的 <code>flake.nix</code>(有关详细信息,请查看 <a href="https://microvm-nix.github.io/microvm.nix/">microvm.nix 文档</a>),并在我的 PC(midna)的 NixOS 配置上启用了 <code>microvm.nixosModules.host</code> 模块。我还创建了一个新的 <code>microvm.nix</code> 文件,在其中声明了我所有的虚拟机。这是我的 <code>flake.nix</code> 的样子:</p> <div class="highlight"><pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>{ </span></span><span style="display:flex;"><span> inputs <span style="color:#666">=</span> { </span></span><span style="display:flex;"><span> nixpkgs <span style="color:#666">=</span> { </span></span><span style="display:flex;"><span> url <span style="color:#666">=</span> <span style="color:#4070a0">&#34;github:nixos/nixpkgs/nixos-25.11&#34;</span>; </span></span><span style="display:flex;"><span> }; </span></span><span style="display:flex; background-color:#d8d8d8"><span> <span style="color:#60a0b0;font-style:italic"># For more recent claude-code</span> </span></span><span style="display:flex; background-color:#d8d8d8"><span> nixpkgs-unstable <span style="color:#666">=</span> { </span></span><span style="display:flex; background-color:#d8d8d8"><span> url <span style="color:#666">=</span> <span style="color:#4070a0">&#34;github:nixos/nixpkgs/nixos-unstable&#34;</span>; </span></span>
查看原文
查看缓存全文

缓存时间: 2026/05/16 03:32

# 在 NixOS 上使用 microvm.nix 搭建编码代理虚拟机 来源:https://michael.stapelberg.ch/posts/2026-02-01-coding-agent-microvm-nix/ ## 目录 - [参见](#参见) - [配置 microvm.nix](#配置-microvmnix) - [第 1 步:网络准备](#第-1-步网络准备) - [第 2 步:`flake.nix`](#第-2-步-flakenix) - [第 3 步:`microvm.nix`](#第-3-步-microvmnix) - [第 4 步:`microvm-base.nix`](#第-4-步-microvm-basenix) - [第 5 步:`microvm-home.nix`](#第-5-步-microvm-homenix) - [第 6 步:`goprotobuf.nix`](#第-6-步-goprotobufnix) - [运行虚拟机](#运行虚拟机) - [使用 Claude 创建虚拟机](#使用-claude-创建虚拟机) - [使用 Claude Code 复制此配置](#使用-claude-code-复制此配置) - [结论](#结论) 我已经开始欣赏[编码代理](https://en.wikipedia.org/wiki/AI-assisted_software_development)作为处理计算机程序代码的有用工具——无论是学习程序架构、诊断 Bug 还是开发概念验证。根据使用场景,审查代理想要运行的每条命令很快就会变得繁琐且耗时。为了安全地运行编码代理而无需审查,我希望有一个虚拟机(VM)解决方案:代理无法访问我的个人文件,即使代理被恶意软件攻陷也无大碍——我可以直接丢弃虚拟机并重新开始。比起设置一个有状态的虚拟机并在需要时重新安装(哎呀!),我更喜欢临时虚拟机的模式:磁盘上不持久保留任何内容,除了显式与宿主机共享的部分。 [microvm.nix](https://github.com/microvm-nix/microvm.nix) 项目使得在 NixOS 上创建这样的虚拟机变得很容易,本文展示了我如何设置我的虚拟机。 ## 参见 如果你还没听说过 NixOS,可以看看 [NixOS Wikipedia 页面](https://en.wikipedia.org/wiki/NixOS) 和 [nixos.org](https://nixos.org/)。我[在 2025 年谈论过为何切换到 Nix](https://michael.stapelberg.ch/talks/#2025),并发表过 [几篇关于 Nix 的博客文章](https://michael.stapelberg.ch/posts/tags/nix/)。 要理解 AI 代理的威胁模型,请阅读 Simon Willison 的《AI 代理的致命三重威胁:私有数据、不可信内容和外部通信》(2025 年 6 月)(https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/)。本文处理威胁模型的方法是将“私有数据”这一部分从方程中移除。 如果你想了解沙盒的整个领域,请查看 Luis Cardoso 的《AI 沙盒实用指南》(2026 年 1 月)(https://www.luiscardoso.dev/blog/sandboxes-for-ai)。本文不会比较不同解决方案,只展示一条可行的路径。 最后,也许你不想自己构建/运行沙盒基础设施。好消息是:沙盒是热门话题,许多商业服务正在涌现以解决这一需求。例如,David Crawshaw 和 Josh Bleecher Snyder(我都是通过 Go 社区认识的)最近推出了 [exe.dev](https://blog.exe.dev/meet-exe.dev),一个面向代理的虚拟机托管服务。另一个例子是 Fly.io,他们推出了 [Sprites](https://fly.io/blog/code-and-let-live/)。 ## 配置 microvm.nix 让我们直接进入正题!接下来的几个小节将带你了解我如何配置我的设置。 ### 第 1 步:网络准备 首先,我创建了一个新的 `microbr` 桥接,使用 `192.168.33.1/24` 作为 IP 地址范围,并通过 `eno1` 网络接口执行 NAT。所有 `microvm*` 接口都将添加到该桥接: ```nix systemd.network.netdevs."20-microbr".netdevConfig = { Kind = "bridge"; Name = "microbr"; }; systemd.network.networks."20-microbr" = { matchConfig.Name = "microbr"; addresses = [ { Address = "192.168.83.1/24"; } ]; networkConfig = { ConfigureWithoutCarrier = true; }; }; systemd.network.networks."21-microvm-tap" = { matchConfig.Name = "microvm*"; networkConfig.Bridge = "microbr"; }; networking.nat = { enable = true; internalInterfaces = [ "microbr" ]; externalInterface = "eno1"; }; ``` ### 第 2 步:`flake.nix` 然后,我将 `microvm` 模块作为新输入添加到我的 `flake.nix`(详情请查看 [microvm.nix 文档](https://microvm-nix.github.io/microvm.nix/)),并在我的 PC(midna)的 NixOS 配置上启用了 `microvm.nixosModules.host` 模块。我还创建了一个新的 `microvm.nix` 文件,其中声明了我所有的虚拟机。以下是我的 `flake.nix` 内容: ```nix { inputs = { nixpkgs = { url = "github:nixos/nixpkgs/nixos-25.11"; }; # 为了更新版本的 claude-code nixpkgs-unstable = { url = "github:nixos/nixpkgs/nixos-unstable"; }; stapelbergnix = { url = "github:stapelberg/nix"; inputs.nixpkgs.follows = "nixpkgs"; }; zkjnastools = { url = "github:stapelberg/zkj-nas-tools"; inputs.nixpkgs.follows = "nixpkgs"; }; microvm = { url = "github:microvm-nix/microvm.nix"; inputs.nixpkgs.follows = "nixpkgs"; }; home-manager = { url = "github:nix-community/home-manager/release-25.11"; inputs.nixpkgs.follows = "nixpkgs"; }; configfiles = { url = "github:stapelberg/configfiles"; flake = false; # 仓库不是 flake }; }; outputs = { self, stapelbergnix, zkjnastools, nixpkgs, nixpkgs-unstable, microvm, home-manager, configfiles, }@inputs: let system = "x86_64-linux"; pkgs = import nixpkgs { inherit system; config.allowUnfree = false; }; pkgs-unstable = import nixpkgs-unstable { inherit system; config.allowUnfree = true; }; in { nixosConfigurations = { midna = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; specialArgs = { inherit inputs; }; modules = [ (import ./configuration.nix) stapelbergnix.lib.userSettings # 使用 systemd 进行网络配置 stapelbergnix.lib.systemdNetwork # 使用 systemd-boot 作为引导加载程序 stapelbergnix.lib.systemdBoot # 在 tailnet 中运行 prometheus node exporter stapelbergnix.lib.prometheusNode zkjnastools.nixosModules.zkjbackup microvm.nixosModules.host ./microvm.nix ]; }; }; }; } ``` ### 第 3 步:`microvm.nix` 下面的 `microvm.nix` 声明了两个 microvm:一个用于 Emacs(我想了解更多),另一个用于 Go Protobuf(一个我熟悉的代码库,可用于理解 Claude 的能力): ```nix { config, lib, pkgs, inputs, ... }: let inherit (inputs) nixpkgs-unstable stapelbergnix microvm configfiles home-manager; microvmBase = import ./microvm-base.nix; in { microvm.vms.emacsvm = { autostart = false; config = { imports = [ stapelbergnix.lib.userSettings microvm.nixosModules.microvm (microvmBase { hostName = "emacsvm"; ipAddress = "192.168.83.6"; tapId = "microvm4"; mac = "02:00:00:00:00:05"; workspace = "/home/michael/microvm/emacs"; inherit nixpkgs-unstable configfiles home-manager stapelbergnix; }) ./microvms/emacs.nix ]; }; }; microvm.vms.goprotobufvm = { autostart = false; config = { imports = [ stapelbergnix.lib.userSettings microvm.nixosModules.microvm (microvmBase { hostName = "goprotobufvm"; ipAddress = "192.168.83.7"; tapId = "microvm5"; mac = "02:00:00:00:00:06"; workspace = "/home/michael/microvm/goprotobuf"; inherit nixpkgs-unstable configfiles home-manager stapelbergnix; extraZshInit = '' export GOPATH=$HOME/go export PATH=$GOPATH/bin:$PATH ''; }) ./microvms/goprotobuf.nix ]; }; }; } ``` ### 第 4 步:`microvm-base.nix` `microvm-base.nix` 模块接受这些参数并声明: - 网络设置:我喜欢使用 `systemd-networkd(8)`(https://manpages.debian.org/systemd-networkd.8) 和 `systemd-resolved(8)`(https://manpages.debian.org/systemd-resolved.8)。 - 共享目录: - 工作空间目录,例如 `~/microvm/emacs` - 宿主机的 Nix store,以便虚拟机可以从缓存中访问软件(通常如此) - 该虚拟机的 SSH 主机密钥 - `~/claude-microvm`,这是一个单独的状态目录,仅用于 microvm 中。 - 一个 8 GB 的磁盘覆盖层(var.img),存储在 `/var/lib/microvms/` 中 - `cloud-hypervisor`(QEMU 也效果很好!)作为虚拟机监控程序,配备 8 个 vCPU 和 4 GB RAM。 - 解决 systemd 尝试卸载 `/nix/store` 的问题(会导致死锁)。 展开完整的 `microvm-base.nix` 代码 ```nix { hostName, ipAddress, tapId, mac, workspace, nixpkgs-unstable, configfiles, home-manager, stapelbergnix, extraZshInit ? "", }: { config, lib, pkgs, ... }: let system = pkgs.stdenv.hostPlatform.system; pkgsUnstable = import nixpkgs-unstable { inherit system; config.allowUnfree = true; }; in { imports = [ home-manager.nixosModules.home-manager ]; # home-manager configuration home-manager.useGlobalPkgs = true; home-manager.useUserPackages = true; home-manager.extraSpecialArgs = { inherit configfiles stapelbergnix; }; home-manager.users.michael = { imports = [ ./microvm-home.nix ]; microvm.extraZshInit = extraZshInit; }; # Claude Code CLI (来自 nixpkgs-unstable, unfree) environment.systemPackages = [ pkgsUnstable.claude-code ]; networking.hostName = hostName; system.stateVersion = "25.11"; services.openssh.enable = true; # 为了匹配 midna(宿主机) users.groups.michael = { gid = 1000; }; users.users.michael = { group = "michael"; }; services.resolved.enable = true; networking.useDHCP = false; networking.useNetworkd = true; networking.tempAddresses = "disabled"; systemd.network.enable = true; systemd.network.networks."10-e" = { matchConfig.Name = "e*"; addresses = [ { Address = "${ipAddress}/24"; } ]; routes = [ { Gateway = "192.168.83.1"; } ]; }; networking.nameservers = [ "8.8.8.8" "1.1.1.1" ]; # 禁用防火墙以实现更快的启动和更少的麻烦; # 反正我们处于 NAT 层后面。 networking.firewall.enable = false; systemd.settings.Manager = { # 快速关机/重启! https://mas.to/@zekjur/113109742103219075 DefaultTimeoutStopSec = "5s"; }; # 修复 microvm 关机挂起问题 (issue #170): # 如果没有这个,systemd 在关机时会尝试卸载 /nix/store, # 但 umount 位于 /nix/store 中,导致死锁。 systemd.mounts = [ { what = "store"; where = "/nix/store"; overrideStrategy = "asDropin"; unitConfig.DefaultDependencies = false; } ]; # 使用从虚拟机外部挂载的 SSH 主机密钥(保持不变)。 services.openssh.hostKeys = [ { path = "/etc/ssh/host-keys/ssh_host_ed25519_key"; type = "ed25519"; } ]; microvm = { # 启用可写的 nix store 覆盖层,以便 nix-daemon 工作。 # 这是 home-manager 激活所必需的。 # 默认使用 tmpfs(临时),这没问题,因为我们 # 不会在虚拟机中构建任何东西。 writableStoreOverlay = "/nix/.rw-store"; volumes = [ { mountPoint = "/var"; image = "var.img"; size = 8192; # MB } ]; shares = [ { # 对于由 systemd 启动的 MicroVM,使用 proto = "virtiofs" proto = "virtiofs"; tag = "ro-store"; # 宿主机上的 /nix/store 将被获取,这样就不需要为它构建 # squashfs/erofs 了。 source = "/nix/store"; mountPoint = "/nix/.ro-store"; } { proto = "virtiofs"; tag = "ssh-keys"; source = "${workspace}/ssh-host-keys"; mountPoint = "/etc/ssh/host-keys"; } { proto = "virtiofs"; tag = "claude-credentials"; source = "/home/michael/claude-microvm"; mountPoint = "/home/michael/claude-microvm"; } { proto = "virtiofs"; tag = "workspace"; source = workspace; mountPoint = workspace; } ]; interfaces = [ { type = "tap"; id = tapId; mac = mac; } ]; hypervisor = "cloud-hypervisor"; vcpu = 8; mem = 4096; socket = "control.socket"; }; } ``` ### 第 5 步:`microvm-home.nix` `microvm-base.nix` 进而引入了 `microvm-home.nix`,它配置 home-manager 以: - 使用我的配置设置 Zsh - 使用我的配置设置 Emacs - 在共享目录 `~/claude-microvm` 中设置 Claude Code。 展开完整的 `microvm-home.nix` 代码 ```nix { config, pkgs, lib, configfiles, stapelbergnix, ... }: { options.microvm = { extraZshInit = lib.mkOption { type = lib.types.lines; default = ""; description = "要添加到 zsh initContent 的额外行"; }; }; config = { home.username = "michael"; home.homeDirectory = "/home/michael"; programs.zsh = { enable = true; history = { size = 4000; save = 10000000; ignoreDups = true; share = false; append = true; }; initContent = '' ${builtins.readFile "${configfiles}/zshrc"} export CLAUDE_CONFIG_DIR=/home/michael/claude-microvm ${config.microvm.extraZshInit} ''; }; programs.emacs = { enable = true; package = stapelbergnix.lib.emacsWithPackages { inherit pkgs; }; }; home.file.".config/emacs" = { source = "${configfiles}/config/emacs"; }; home.stateVersion = "25.11"; programs.home-manager.enable = true; }; } ``` ### 第 6 步:`goprotobuf.nix` `goprotobuf.nix` 提供了一系列必需和便捷的包: ```nix # Project-specific configuration for goprotobufvm { pkgs, ... }: { # Development environment for Go Protobuf environment.systemPackages = with pkgs; [ # Go toolchain go gopls delve protobuf gnumake gcc git ripgrep ]; } ``` ### 运行虚拟机 让我们创建工作空间目录并创建 SSH 主机密钥: ```bash mkdir -p ~/microvm/emacs/ssh-host-keys ssh-keygen -t ed25519 -N "" \ -f ~/microvm/emacs/ssh-host-keys/ssh_host_ed25519_key ``` 现在我们可以启动虚拟机: ```bash sudo systemctl start microvm@emacsvm ``` 它在几秒钟内启动并响应 ping。然后,SSH 进入虚拟机(也许在 `tmux(1)`(https://manpages.debian.org/tmux.1) 会话中),在共享的工作空间目录中运行 Claude(或你选择的编码代理),无需权限提示: ```bash % ssh 192.168.83.2 emacsvm% cd microvm/emacs emacsvm% claude --dangerously-skip-permissions ``` 这是在此类设置中运行 Claude 的样子: Claude Code 处于“绕过权限”模式 (https://michael.stapelberg.ch/posts/2026-02-01-coding-agent-microvm-nix/2026-01-28-neofetch-featured.png) ## 使用 Claude 创建虚拟机 在完成一次设置 MicroVM 的过程后,它就变得乏味了。我很好奇 [Claude Skills](https://code.claude.com/docs/en/skills) 是否能帮助完成这样的任务。Skills 是 markdown 文件,指示 Claude 在特定情况下执行某些步骤。我创建了 `~/.claude/skills/create-microvm/SKILL.md`,内容如下: ```markdown --- name: create-microvm description: 在 midna 上创建一个新的 microvm 虚拟机,用于在其中运行 Claude, 包括源代码仓库和构建依赖项。当用户要求创建新的 microvm 时使用。 --- 检查 ~/machines/midna 中现有的结构(使用 Flakes 的 NixOS 配置),其中包括 ~/machines/midna/microvms/ 目录中的多个 MicroVM。 然后,为用户要求创建的 microvm 创建类似的结构。请确保考虑: 1. 创建一个以 NAME(microvm 名称)命名的新子目录。 2. 在 microvm.nix 中创建一个条目,类似于现有 microvm,但要: 3. 将 hostname 改为 NAME 4. 更改 IP 地址(例如 192.168.83.3):查找已使用的,并选择下一个空闲的 5. 将 workspace share 改为 /home/michael/microvm/NAME 6. 根据用户请求包含新 microvm 的构建依赖项 7. 创建 ssh-host-keys 目录 8. 生成 SSH 主机密钥 9. 根据用户请求将源代码仓库克隆/下载到此 microvm 定义好 microvm 后,更新 ~/machines/midna 以包含它。 要验证,构建配置(但不要部署)。 你需要先将更改提交到 microvm,然后 ~/machines/midna 才能看到它们。 ``` 当使用此技能与 Claude Code(测试版本:v2.0.76 和 v2.1.15)配合使用时,采用 Opus 4.5 模型 (https://www.ant

相似文章

使用Nix的开发环境:四个快速示例

Michael Stapelberg

本教程演示了使用Nix设置开发环境的四种方法,包括交互式一次性使用、配置文件以及密封的Nix Flakes,并以GoCV和OpenCV为例。

我喜欢的 NixOS 声明式安装方式

Michael Stapelberg

一份关于使用 nixos-anywhere 等工具通过网络声明式安装 NixOS 的指南,重点强调在版本控制下管理配置文件。

在 VPS 上运行我的智能体

Lobsters Hottest

作者概述了一种在隔离 VPS 上运行 AI 编码智能体的方法,旨在实现自主、异步工作,同时不危及本地机器的安全性。