我们发现了什么
# qh — 面向 AI 代理(和人类)的 QEMU 测试框架 在几秒钟内启动一个裸内核镜像(或现成的 Alpine 镜像),通过内置的桥接代理与其通信(类似于 qemu-guest-agent,但更轻量且与内核无关),获得网络功能,并在不到一秒的时间内重建根文件系统。标题:GitHub - b3s3da/qemu-harness:面向 AI 代理的 QEMU 测试框架:几秒钟内启动 aarch64/arm/riscv64/x86_64 内核,通过 guest agent 执
- 来源:GitHub(发现于 2026-10-06)
- 证据等级:D · 发现产品或需求信号,暂未获得可核验的商业证据。
- 商业模式:待核验
- 主题:独立产品
- 初筛评分:15.1/100 · 收录 1 次
证据,比故事更重要。
规则清洗与初筛,未经人工商业核验。原文语境、实际客户和付费情况仍需自行验证。
引用与数字披露
来源类型(原作者自述/第三方测算/媒体转引)需采集端标注,本版尚未落字段。
- 作者
- 未标注
- 抓取日期
- 来源类型
- 未标注
- 币种
- 未标注
- 口径
- 未标注
- 披露主体
- 未标注
- 披露日期
- 未标注
中文辅助译文(全文)
qh — 一个面向 AI 代理(以及人类)的 QEMU 测试工具
在几秒内启动一个裸内核镜像(或现成的 Alpine 镜像),通过虚拟机内部桥接代理与其通信
(可以理解为 qemu-guest-agent,但更小巧且不依赖于特定内核),获得网络连接,并在不到一秒内重建根文件系统。
专为 IoT / 嵌入式内核仿真 而构建:支持 aarch64、arm32、riscv64 和 x86_64 客户机,可使用你指定的任何 machine/DTB/cmdline。
qh up→ 虚拟机就绪(代理响应中)约需 2–5 秒,qh exec 'cmd'→ 以 JSON 形式返回 stdout/stderr/exit code。- Rootfs = Alpine 用户空间 + 你的 overlay 目录,在主机上打包成 initramfs 耗时约 0.3 秒(
qh reload)。无需 root 权限,无需 WSL,无需挂载。 - 兼容没有 virtio-net 的标准内核:代理将以太网帧通过串行通道隧道传输到 QEMU 的用户模式网络。
- 内置一个 skill(
skill/SKILL.md),以便 Claude Code / Grok 或任何支持 SKILL.md 的代理知道如何驱动它。 - 以 Windows 优先(在 Windows 10 + QEMU 11 上测试通过),主机端仅使用 Python 标准库,Go 仅用于交叉编译客户机代理。Linux/macOS 也可使用。
快速开始
Windows - 一行命令(下载测试工具到 ~\tools\qemu-harness,提示通过 winget 安装 Python / QEMU / Go,
构建客户机代理,将 qh 添加到你的 PATH,为 Claude Code 和 Grok 安装代理 skill):
irm https://raw.githubusercontent.com/b3s3da/qemu-harness/main/install.ps1 | iex选项(-Yes = 永不询问,-Arch all,-Dir,-NoDeps,-NoPath,-NoSkills,-Smoke):
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/b3s3da/qemu-harness/main/install.ps1))) -Yes -Arch all -Smoke将脚本通过管道传给 iex 会以不可见的方式执行——如果你愿意,可以克隆仓库(或下载 install.ps1),阅读其内容,然后运行 .\install.ps1。
Linux / macOS:git clone ... && ./install.sh(需要 Python 3、qemu-system-*、Go)。
然后,在任何项目文件夹中(先打开一个新的终端,以便 PATH 生效):
mkdir lab ; cd lab
qh up --kernel alpine:aarch64 # or --kernel path\to\Image
qh exec 'uname -a; ip -4 -o a show eth0'
qh down要求:Python >= 3.8,QEMU(qemu-system-<arch> 在 PATH 上或位于 C:\Program Files\qemu),Go >= 1.22(用于 qh setup),首次运行需要联网。
安装程序是幂等的:重新运行它会原地更新测试工具并保留 cache/。
命令
| 命令 | 功能 | |
|---|---|---|
| `qh setup [--arch A\ | all]` | 获取 Alpine 微型 rootfs,构建客户机代理(缓存在 cache/<arch>) |
qh up [--kernel K] [-n NAME] | 构建 initramfs,启动,等待代理 | |
qh exec [--json] [--timeout N] [--bg] CMD… | 在客户机中运行;传递 exit code;支持 --cwd、-e K=V、--stdin、--argv | |
qh put SRC DST / qh get SRC DST | 复制文件或目录(在线使用 zlib 压缩;请保持文件较小,参见性能说明) | |
qh reload [任何虚拟机选项] | 重建 rootfs 并使用相同端口重新启动;kernel/dtb/mem/cmdline 可更改 | |
qh fwd HOST:GUEST | 在运行时添加主机→客户机的 TCP 转发(0 = 选择空闲的主机端口) | |
qh logs [-f] [--tail N] / qh console --send CMD | 串行控制台日志 / 与其交互 | |
qh probe [--kernel K] | 内核支持的功能以及 qh 会选择的传输方式 | |
qh dtb -o m.dtb | 转储 QEMU 生成的设备树(已打包),使用 dtc 编辑,通过 --dtb 回传 | |
| `qh kernel fetch ARCH [virt\ | lts]` | 下载 Alpine 内核及 virtio/tun/9p 模块 |
qh up --dry-run | 打印准确的 QEMU 命令行 | |
qh ls / down / rm / qmp CMD | 生命周期与原始 QMP |
所有命令都支持 --json。状态保存在你执行命令所在目录的 ./.qh/<name>/ 中(支持多个虚拟机:-n NAME)。
配置(项目中的 qh.json,回退到 qh.example.json)
{ "kernel": "alpine:aarch64", "mem": "512M", "smp": 2, "fs": ["fs"], "pkgs": ["dropbear", "mosquitto"], "fwd": ["2222:22"] }每个键都有对应的 CLI 标志(--arch --kernel --initrd --bios --machine --cpu --mem --smp --dtb --disk --append --net --fs --pkg --fwd --chan --nic --bus --chan-tty --qemu-arg)。
kernel 也可以是 alpine:<arch>[:virt|lts]。
自定义你的客户机
Overlay:fs 中列出的目录下的所有文件都会被复制到 Alpine rootfs 之上(后出现的覆盖先出现的)。可以将固件、配置、服务放在那里。
可执行位会被推断(#!、ELF、bin/、sbin/)。fs/etc/qh.d/rc.local 在虚拟机被声明为就绪之前运行;cmdline 上的 qh.init=/path 会运行一个钩子。
软件包:pkgs 中的名称会根据 Alpine 的索引解析(包含依赖),并在主机上解包——无需 apk。
内核模块:提供一个完整的树(lib/modules/<ver>/modules.dep,未压缩的 .ko),init 时通过 modprobe 加载 virtio/tun/9p;零散的 `.ko + modules.order 通过 insmod` 加载。
* 自带的 overlay 会启动 dropbear(root,空密码——仅限实验环境!)、mosquitto 和 httpd。
工作原理
qh CLI ──tcp──► per-VM daemon ──tcp──► QEMU chardev ══ virtio-serial / PCI-UART / spare UART ══► qh-agent (Go, in guest)
│ │ exec/put/get
└─ ethernet frames ◄──► QEMU "stream" netdev ─ hub ─ slirp (10.0.2.0/24, DNS, hostfwd) ◄── tap eth0 (if no virtio-net)qh 读取内核内嵌的配置(/proc/config.gz)或 <kernel>.config,并选择最佳传输方式:如果存在 virtio-console + virtio-net(PCI 或 MMIO),则使用它们;否则使用内置的 8250-PCI UART(或通过 --chan serial --chan-tty 指定的备用板载 UART),并在客户机中使用 tap 设备。
处理没有 devtmpfs 的内核(mdev -s)。线协议使用 JSON 行(agent/main.go),以太网帧使用 F<base64> 行。
性能说明
使用 virtio-net(Alpine 内核,大多数发行版内核)时,网络速度正常。在标准的 Android GKI 镜像上(无 NIC 驱动,virtio 作为模块),隧道提供约 15 KB/s 写入客户机、75 KB/s 读出的速度——对于脚本、MQTT、HTTP 探测足够;将大型负载放在 fs/ 中并使用 qh reload。
故障排除
代理未响应:qh logs --tail 80,然后qh probe。既无 virtio-console 也无 8250-PCI 的内核需要--chan serial --chan-tty /dev/ttyXX,或--initrd X --no-wait+qh console。- Git Bash 会将
/tmp/x参数改写为 Windows 路径——设置MSYS_NO_PATHCONV=1。 - 无闪烁的控制台窗口:QEMU 和守护进程使用
CREATE_NO_WINDOW启动。 - aarch64/arm/riscv64 在 x86 主机上以 TCG 运行(稍慢但可用);在匹配的架构主机上,QEMU 可以使用
--qemu-arg "-accel whpx"/ KVM。
许可证
GPL-3.0-or-later — 参见 LICENSE。客户机用户空间为 Alpine Linux(在安装时下载,每个软件包有各自的许可证)。
译文由上游机器翻译生成,可能有误;判断请以英文原文为准。
英文原文(来源本站未改写)
qh — a QEMU harness for AI agents (and humans)
Boot a bare kernel image (or a ready-made Alpine one) in seconds, talk to it through an in-guest bridge agent
(think qemu-guest-agent, but tiny and kernel-agnostic), get networking, and rebuild the root filesystem in a fraction of a second.
Built for IoT / embedded kernel emulation: aarch64, arm32, riscv64 and x86_64 guests, any machine/DTB/cmdline you throw at it.
qh up→ VM ready (agent answering) in ~2–5 s,qh exec 'cmd'→ stdout/stderr/exit code as JSON.- Rootfs = Alpine userland + your overlay dirs, packed into an initramfs on the host in ~0.3 s (
qh reload). No root, no WSL, no mounts. - Works with stock kernels that have no virtio-net: the agent tunnels ethernet over a serial channel into QEMU's user-mode network.
- Ships a skill (
skill/SKILL.md) so Claude Code / Grok / any SKILL.md-aware agent knows how to drive it. - Windows-first (tested on Windows 10 + QEMU 11), pure Python stdlib on the host, Go only to cross-build the guest agent. Linux/macOS work too.
Quick start
Windows - one line (downloads the harness to ~ ools\qemu-harness, offers to install Python / QEMU / Go via winget,
builds the guest agent, adds qh to your PATH, installs the agent skill for Claude Code and Grok):
irm https://raw.githubusercontent.com/b3s3da/qemu-harness/main/install.ps1 | iexOptions (-Yes = never ask, -Arch all, -Dir, -NoDeps, -NoPath, -NoSkills, -Smoke):
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/b3s3da/qemu-harness/main/install.ps1))) -Yes -Arch all -SmokePiping a script into iex runs it unseen - if you prefer, clone the repo (or download install.ps1), read it, and run .\install.ps1.
Linux / macOS: git clone ... && ./install.sh (needs Python 3, qemu-system-*, Go).
Then, in any project folder (open a new terminal first so PATH is picked up):
mkdir lab ; cd lab
qh up --kernel alpine:aarch64 # or --kernel path o\Image
qh exec 'uname -a; ip -4 -o a show eth0'
qh downRequirements: Python >= 3.8, QEMU (qemu-system-<arch> on PATH or C:\Program Files\qemu), Go >= 1.22 (for qh setup), internet for the first run.
The installer is idempotent: re-running it updates the harness in place and keeps cache/.
Commands
| command | what it does | |
|---|---|---|
| `qh setup [--arch A\ | all]` | fetch Alpine minirootfs, build the guest agent (cached in cache/<arch>) |
qh up [--kernel K] [-n NAME] | build initramfs, boot, wait for the agent | |
qh exec [--json] [--timeout N] [--bg] CMD… | run in the guest; exit code propagated; --cwd, -e K=V, --stdin, --argv | |
qh put SRC DST / qh get SRC DST | copy files or dirs (zlib on the wire; keep them small, see Performance) | |
qh reload [any VM option] | rebuild rootfs and relaunch with the same ports; kernel/dtb/mem/cmdline may change | |
qh fwd HOST:GUEST | add a host→guest TCP forward at runtime (0 = pick a free host port) | |
qh logs [-f] [--tail N] / qh console --send CMD | serial console log / talk to it | |
qh probe [--kernel K] | what the kernel supports and which transports qh would pick | |
qh dtb -o m.dtb | dump QEMU's generated device tree (packed), edit with dtc, feed back with --dtb | |
| `qh kernel fetch ARCH [virt\ | lts]` | download an Alpine kernel + virtio/tun/9p modules |
qh up --dry-run | print the exact QEMU command line | |
qh ls / down / rm / qmp CMD | lifecycle and raw QMP |
Everything takes --json. State lives in ./.qh/<name>/ of the directory you run in (several VMs: -n NAME).
Configuration (qh.json in your project, falls back to qh.example.json)
{ "kernel": "alpine:aarch64", "mem": "512M", "smp": 2, "fs": ["fs"], "pkgs": ["dropbear", "mosquitto"], "fwd": ["2222:22"] }Every key has a CLI flag (--arch --kernel --initrd --bios --machine --cpu --mem --smp --dtb --disk --append --net --fs --pkg --fwd --chan --nic --bus --chan-tty --qemu-arg).
kernel may also be alpine:<arch>[:virt|lts].
Making the guest yours
- Overlay: everything under the directories listed in
fsis copied over the Alpine rootfs (later wins).Put firmware, configs, services there.Executable bits are inferred (#!, ELF,bin/,sbin/).fs/etc/qh.d/rc.localruns before the VM is declared ready;qh.init=/pathon the cmdline runs a hook. - Packages: names in
pkgsare resolved against Alpine's index (deps included) and unpacked on the host — noapkneeded. - Kernel modules: ship a full tree (
lib/modules/<ver>/modules.dep, uncompressed.ko) and initmodprobes virtio/tun/9p;loose*.ko+modules.orderareinsmoded. - The bundled overlay starts dropbear (root, empty password — lab only!
), mosquitto, and httpd.
How it works
qh CLI ──tcp──► per-VM daemon ──tcp──► QEMU chardev ══ virtio-serial / PCI-UART / spare UART ══► qh-agent (Go, in guest)
│ │ exec/put/get
└─ ethernet frames ◄──► QEMU "stream" netdev ─ hub ─ slirp (10.0.2.0/24, DNS, hostfwd) ◄── tap eth0 (if no virtio-net)qh reads the kernel's embedded config (/proc/config.gz) or <kernel>.config and picks the best transport: virtio-console + virtio-net
(PCI or MMIO) when present; otherwise the built-in 8250-PCI UART (or a spare board UART via --chan serial --chan-tty) with a tap device in the guest.
Kernels without devtmpfs are handled (mdev -s). The wire protocol is JSON lines (agent/main.go), ethernet frames are F<base64> lines.
Performance notes
With virtio-net (Alpine kernels, most distro kernels) the network is normal speed. On a stock Android GKI image (no NIC drivers, virtio as modules)
the tunnel gives roughly 15 KB/s into the guest and 75 KB/s out — fine for scripts, MQTT, HTTP probes; put big payloads in fs/ and qh reload instead.
Troubleshooting
agent did not respond:qh logs --tail 80, thenqh probe. A kernel with neither virtio-console nor 8250-PCI needs--chan serial --chan-tty /dev/ttyXX, or--initrd X --no-wait+qh console.- Git Bash rewrites
/tmp/xarguments into Windows paths — setMSYS_NO_PATHCONV=1. - No flashing console windows: QEMU and the daemon start with
CREATE_NO_WINDOW. - aarch64/arm/riscv64 run under TCG on x86 hosts (slow-ish but fine); on a matching host QEMU may use
--qemu-arg "-accel whpx"/ KVM.
License
GPL-3.0-or-later — see LICENSE. The guest userland is Alpine Linux (downloaded at setup time, own licenses per package).
这条还缺什么证据?
下面每条都由本条已有字段推出(等级、理由、商业模式、来源次数、是否演示), 本站不生成推测性结论;通用验证方法放在方法论页。
- 可核验的收入或付费证据查官网定价页与付费口径;第三方数据源(如 GetLatka)只作旁证,需标注来源与时点。
- 商业模式未定确认按席位/按用量/授权还是开源托管版收费;开源项目另查 LICENSE 与是否存在付费版。
- 只有单一来源找一手站点或其他渠道是否重复出现同一产品;社区热帖数量不等于商业进展。
通用验证清单(谁有这个问题/谁愿意付费/一个人能交付哪一小步)见我们的筛选方法。