cmux-freestyle
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesecmux Freestyle
cmux Freestyle
Use this skill when a user wants a Freestyle VM snapshot that the cmux backend can boot Cloud VMs from. It lives in its own public repo, , so anyone with a Freestyle API key can run one shell script and get back a id.
manaflow-ai/cmux-freestyleFREESTYLE_SANDBOX_SNAPSHOTFreestyle snapshots are scoped to the account that created them. A snapshot id from manaflow's account, or from any other user, will not work for a different Freestyle account. Every user has to run the setup script against their own . There is no shortcut.
FREESTYLE_API_KEY当用户需要一个可供cmux后端启动Cloud VM的Freestyle VM快照时,可使用本技能。它托管在独立的公开仓库中,因此任何拥有Freestyle API密钥的用户只需运行一个Shell脚本,即可获得一个 ID。
manaflow-ai/cmux-freestyleFREESTYLE_SANDBOX_SNAPSHOTFreestyle快照的作用范围仅限于创建它的账户。来自manaflow账户或其他任何用户的快照ID,无法在其他Freestyle账户中使用。每个用户都必须使用自己的运行设置脚本,没有捷径可走。
FREESTYLE_API_KEYWhen to use
使用场景
- User asks how to point their own cmux at Freestyle.
- User self-hosts the cmux web backend and needs a snapshot pinned to a known cmux release.
- User wants to rebuild the cmux Cloud VM image on their own Freestyle account.
- User wants to iterate on the standalone repo () instead of the in-repo builder at
cmux-freestyle.repo/web/scripts/build-cloud-vm-images.ts
For internal cmux development that pushes a new snapshot to manaflow's Freestyle account and updates , keep using . This skill is the external-user path.
repo/web/services/vms/images/manifest.jsonrepo/web/scripts/build-cloud-vm-images.ts- 用户询问如何将自己的cmux指向Freestyle。
- 用户自托管cmux Web后端,需要一个固定到已知cmux版本的快照。
- 用户希望在自己的Freestyle账户上重新构建cmux Cloud VM镜像。
- 用户希望对独立仓库()进行迭代开发,而非使用仓库内的构建工具
cmux-freestyle。repo/web/scripts/build-cloud-vm-images.ts
对于将新快照推送到manaflow的Freestyle账户并更新的内部cmux开发工作,请继续使用。本技能面向外部用户提供操作路径。
repo/web/services/vms/images/manifest.jsonrepo/web/scripts/build-cloud-vm-images.tsWhat it builds
构建内容
A Freestyle snapshot from a that mirrors in the in-repo builder:
DockerfilefreestyleBaseDockerfileContent- ,
ubuntu:24.04, the same shell package set, the Python/OpenSSL shim required by the cmux browser proxy.C.UTF-8 - Linux/amd64 downloaded from a pinned
cmuxd-remoteGitHub release, SHA-256 verified during the image build againstmanaflow-ai/cmux.cmuxd-remote-checksums.txt - symlinked to
/usr/local/bin/cmux.cmuxd-remote - Node.js, Bun, plus pinned coding agent CLIs (Claude Code, OpenCode, Codex, Pi).
- Linux user with passwordless sudo.
cmux - Systemd unit running
cmuxd-ws.serviceon Freestyle portcmuxd-remote serve --ws --listen 0.0.0.0:7777 --auth-lease-file ... --rpc-auth-lease-file ....443 -> 7777
The image runs the same smoke tests as the in-repo builder, so failures show up at snapshot build time, not later inside a live VM.
基于构建Freestyle快照,该文件与仓库内构建工具中的保持一致:
DockerfilefreestyleBaseDockerfileContent- 基础镜像为,字符编码为
ubuntu:24.04,包含相同的Shell软件包集,以及cmux浏览器代理所需的Python/OpenSSL垫片。C.UTF-8 - 从固定的GitHub版本下载
manaflow-ai/cmuxLinux/amd64版本,在镜像构建过程中通过cmuxd-remote进行SHA-256验证。cmuxd-remote-checksums.txt - 将软链接至
/usr/local/bin/cmux。cmuxd-remote - 预装Node.js、Bun,以及固定版本的编码Agent CLI(Claude Code、OpenCode、Codex、Pi)。
- 创建Linux用户,拥有免密码sudo权限。
cmux - 配置Systemd单元,运行
cmuxd-ws.service,并将Freestyle端口cmuxd-remote serve --ws --listen 0.0.0.0:7777 --auth-lease-file ... --rpc-auth-lease-file ...转发至443。7777
该镜像会运行与仓库内构建工具相同的冒烟测试,因此构建失败会在快照构建阶段就暴露出来,而非在后续的实时VM运行中。
How to use it
使用方法
The repo is self-contained; no cmux checkout required.
bash
git clone https://github.com/manaflow-ai/cmux-freestyle.git
cd cmux-freestyle
export FREESTYLE_API_KEY=fk_...
./setup.shOr the one-liner:
bash
FREESTYLE_API_KEY=fk_... \
curl -fsSL https://raw.githubusercontent.com/manaflow-ai/cmux-freestyle/main/install.sh | bashUseful flags / env on (the default subcommand):
./setup.sh snapshot- or
--release <tag>pins the cmuxd-remote release. Default is the latest stableCMUX_RELEASE_TAG=<tag>release.manaflow-ai/cmux - or
--name <name>sets the Freestyle snapshot name.CMUX_FREESTYLE_SNAPSHOT_NAME - or
--skip-cacheforces a clean Freestyle rebuild.CMUX_FREESTYLE_SKIP_CACHE=1 - ,
--codex-spec none, etc. drop individual agent CLIs.--claude-spec none - emits a machine-readable result; the human path prints
--jsonat the end.FREESTYLE_SANDBOX_SNAPSHOT=sh-...
The build takes 5 to 15 minutes depending on Freestyle's layer cache.
本仓库是独立的,无需检出cmux代码。
bash
git clone https://github.com/manaflow-ai/cmux-freestyle.git
cd cmux-freestyle
export FREESTYLE_API_KEY=fk_...
./setup.sh或者使用单行命令:
bash
FREESTYLE_API_KEY=fk_... \
curl -fsSL https://raw.githubusercontent.com/manaflow-ai/cmux-freestyle/main/install.sh | bash./setup.sh snapshot- 或
--release <tag>:固定cmuxd-remote的版本。默认使用CMUX_RELEASE_TAG=<tag>的最新稳定版本。manaflow-ai/cmux - 或
--name <name>:设置Freestyle快照的名称。CMUX_FREESTYLE_SNAPSHOT_NAME - 或
--skip-cache:强制Freestyle进行干净重建。CMUX_FREESTYLE_SKIP_CACHE=1 - 、
--codex-spec none等:移除单个Agent CLI。--claude-spec none - :输出机器可读的结果;面向用户的路径会在最后打印
--json。FREESTYLE_SANDBOX_SNAPSHOT=sh-...
构建时长取决于Freestyle的层缓存,通常为5至15分钟。
Full self-host bundle
完整自托管包
./setup.shbash
./setup.sh doctor # validate tools, env, Freestyle key, GitHub release
./setup.sh # mint a snapshot under the user's Freestyle account
./setup.sh web --snapshot sh-xxxxxx # clone manaflow-ai/cmux, write web/.env.local, start Docker Postgres
./setup.sh home --ref feat-ink-rewrite # install cmux-home (Ink TUI) headquarters viewwebmanaflow-ai/cmux~/cmux-freestyle-cmuxweb/.env.localbun install--no-postgresSTACK_SECRET_SERVER_KEYNEXT_PUBLIC_STACK_PROJECT_IDNEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEYgitbundockerhomecmux-home~/cmux-freestyle-home/inkfeat-ink-rewrite--refmainIf is set in the env when runs (the script exports it from the user's and the shell), cmux-home renders a second panel under the workspace list titled . Each row shows the VM id, state, snapshot id (the one from ), and age. This makes the TUI a single dashboard for both local cmux workspaces and the user's Freestyle Cloud VMs, with the same selection cursor walking both panels.
FREESTYLE_API_KEYbun devhome~/.secrets/cmux.envFreestyle VMs (N)./setup.sh snapshotSelecting a VM enables the following actions on the row:
- opens the sandbox workflow: creates a new cmux workspace running
enter. The helper script mints a short-lived Freestyle SSH identity, opens an SSH session throughfreestyle-vm-ssh <vmId>withvm-ssh.freestyle.sh(reverse-forward to the local Subrouter AI gateway on-R 31415:127.0.0.1:31415) plus127.0.0.1:31415forwards for common dev ports (-L,3000,5173,8000), writes a8080inside the VM that points~/.codex/config.tomlat the forwarded subrouter, then drops into a login shell. Codex launched inside the VM in that shell routes through Subrouter on the user's mac. Also opens a browser pane on the right atopenai_base_url.http://127.0.0.1:3000 - opens the local-codex workflow: a normal cmux workspace at the TUI's
ctrl+o, no SSH, plus a browser pane on the right at--cwd. Codex/Claude run on the mac against the local checkout; the VM is treated as a remote dev server.https://<vmId>.vm.freestyle.sh - destroys the VM through the Freestyle SDK.
ctrl+x - on the
ctrl+nheader creates a new VM fromFreestyle VMs (N).FREESTYLE_SANDBOX_SNAPSHOT
Freestyle gateway constraint. The Freestyle SSH gateway at rejects remote port forwarding (). The flag is therefore opt-in and works only for ordinary Linux/macOS sshd hosts.
vm-ssh.freestyle.sh-Rremote port forwarding failed for listen port 31415--reverse-subrouterDefault path for codex inside a Freestyle VM (works today): mints an ephemeral preauth Tailscale key via (tag , expires in 1h), runs inside the VM under userspace networking (), enables tailscaled's HTTP proxy + SOCKS5 server on , writes so every login shell exports //, and writes with . Codex inside the VM then connects to the existing host on the tailnet through the local proxy, so all OpenAI traffic is routed through Subrouter's account scheduling. The cmux-freestyle snapshot already ships the apt package, so first-time bring-up is ~6 s end-to-end; subsequent sessions reuse the existing state.
freestyle-vm-sshtsadmin api POST /tailnet/-/keystag:servertailscale up--tun=userspace-networking127.0.0.1:1055/etc/profile.d/cmux-tailnet-proxy.shHTTP_PROXYHTTPS_PROXYNO_PROXY~/.codex/config.tomlopenai_base_url = "http://subrouter-team.tail41290.ts.net:31415/v1"subrouter-teamtailscaleDisable per-call with , override the subrouter URL with or , override the auth-key with or . Today Subrouter only routes Codex, so use Codex inside the VM until Subrouter adds Claude/OpenCode support.
--no-tailscale--subrouter-url <url>SUBROUTER_REMOTE_URL--tailscale-authkey <key>TAILSCALE_AUTHKEYHelper requires on the mac () and on ().
sshpassbrew install hudochenkov/sshpass/sshpasstsadminPATHskills/tsadmin/scripts/tsadmin./setup.shbash
./setup.sh doctor # 验证工具、环境变量、Freestyle密钥、GitHub版本
./setup.sh # 在用户的Freestyle账户下生成快照
./setup.sh web --snapshot sh-xxxxxx # 克隆manaflow-ai/cmux,写入web/.env.local,启动Docker Postgres
./setup.sh home --ref feat-ink-rewrite # 安装cmux-home(Ink TUI)主控视图webmanaflow-ai/cmux~/cmux-freestyle-cmuxweb/.env.localbun install--no-postgresSTACK_SECRET_SERVER_KEYNEXT_PUBLIC_STACK_PROJECT_IDNEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEYgitbundockerhome~/cmux-freestyle-home/inkcmux-homefeat-ink-rewritemain--ref如果运行时环境中设置了(脚本会从用户的和Shell中导出该变量),cmux-home会在工作区列表下方显示第二个面板,标题为。每一行会显示VM ID、状态、快照ID(来自)和运行时长。这使得TUI成为本地cmux工作区和用户Freestyle Cloud VM的统一仪表板,同一个选择光标可在两个面板间切换。
bun devFREESTYLE_API_KEYhome~/.secrets/cmux.envFreestyle VMs (N)./setup.sh snapshot选择一个VM后,可在该行执行以下操作:
- :打开沙箱工作流:创建一个新的cmux工作区,运行
enter。该辅助脚本会生成一个短期的Freestyle SSH身份,通过freestyle-vm-ssh <vmId>打开SSH会话,参数包含vm-ssh.freestyle.sh(反向转发到本地Subrouter AI网关的-R 31415:127.0.0.1:31415)以及针对常见开发端口(127.0.0.1:31415、3000、5173、8000)的8080转发,在VM内写入-L,将~/.codex/config.toml指向转发后的subrouter,然后进入登录Shell。在该Shell中启动的Codex会通过用户Mac上的Subrouter进行路由。同时会在右侧打开浏览器窗口,指向openai_base_url。http://127.0.0.1:3000 - :打开local-codex工作流:在TUI的
ctrl+o路径创建一个普通的cmux工作区,无需SSH,同时在右侧打开浏览器窗口,指向--cwd。Codex/Claude在Mac上针对本地检出的代码运行;VM被视为远程开发服务器。https://<vmId>.vm.freestyle.sh - :通过Freestyle SDK销毁VM。
ctrl+x - 在标题上按
Freestyle VMs (N):从ctrl+n创建新的VM。FREESTYLE_SANDBOX_SNAPSHOT
Freestyle网关限制:位于的Freestyle SSH网关会拒绝远程端口转发(提示)。因此标志为可选启用,且仅适用于普通Linux/macOS sshd主机。
vm-ssh.freestyle.sh-Rremote port forwarding failed for listen port 31415--reverse-subrouterFreestyle VM内Codex的默认路径(当前可用):通过生成一个临时的预授权Tailscale密钥(标签,1小时后过期),在VM内以用户空间网络模式()运行,在启用tailscaled的HTTP代理+SOCKS5服务器,写入,使每个登录Shell都导出//,并写入,设置。VM内的Codex随后会通过本地代理连接到tailnet上现有的主机,因此所有OpenAI流量都会通过Subrouter的账户调度进行路由。cmux-freestyle快照已预装apt包,首次启动耗时约6秒;后续会话会重用现有状态。
freestyle-vm-sshtsadmin api POST /tailnet/-/keystag:server--tun=userspace-networkingtailscale up127.0.0.1:1055/etc/profile.d/cmux-tailnet-proxy.shHTTP_PROXYHTTPS_PROXYNO_PROXY~/.codex/config.tomlopenai_base_url = "http://subrouter-team.tail41290.ts.net:31415/v1"subrouter-teamtailscale可通过禁用该功能,通过或覆盖subrouter URL,通过或覆盖授权密钥。目前Subrouter仅支持Codex路由,因此在Subrouter添加Claude/OpenCode支持前,请在VM内使用Codex。
--no-tailscale--subrouter-url <url>SUBROUTER_REMOTE_URL--tailscale-authkey <key>TAILSCALE_AUTHKEY该辅助工具需要Mac上安装(),且需在中()。
sshpassbrew install hudochenkov/sshpass/sshpasstsadminPATHskills/tsadmin/scripts/tsadminGitHub auth
GitHub认证
The snapshot builder talks only to public GitHub endpoints ( and the release-asset ). The unauthenticated GitHub API allows 60 requests per hour, which is fine in normal use. If a user hits a 403/429 (shared IP, CI loops, repeated rebuilds), they should set (or ) and the script forwards it on both the API call and the checksums download. Mention this when guiding a CI integration.
/repos/manaflow-ai/cmux/releases/latestcmuxd-remote-checksums.txtGITHUB_TOKENGH_TOKENThe Freestyle SDK only needs ; no GitHub credentials are required for snapshot creation. clones anonymously, so no auth is required there either; only suggest if a user explicitly wants against their own fork.
FREESTYLE_API_KEYsetup.sh webmanaflow-ai/cmuxgh auth logingit push快照构建器仅与公开的GitHub端点通信(和发布资产)。未认证的GitHub API每小时允许60次请求,正常使用下完全足够。如果用户遇到403/429错误(共享IP、CI循环、重复重建),应设置(或),脚本会在API调用和校验和下载时自动使用该令牌。在指导CI集成时需提及这一点。
/repos/manaflow-ai/cmux/releases/latestcmuxd-remote-checksums.txtGITHUB_TOKENGH_TOKENFreestyle SDK仅需要;创建快照无需GitHub凭据。会匿名克隆,因此也不需要认证;仅当用户明确需要向自己的分支执行时,才建议使用。
FREESTYLE_API_KEYsetup.sh webmanaflow-ai/cmuxgit pushgh auth loginPlugging the snapshot into cmux
将快照接入cmux
After the script prints the snapshot id, hand the user the env block for their cmux backend:
bash
FREESTYLE_API_KEY=fk_...
FREESTYLE_SANDBOX_SNAPSHOT=sh-xxxxxxxxxxxxxxxxxxxx
CMUX_VM_DEFAULT_PROVIDER=freestyle
CMUX_VM_FREESTYLE_ENABLED=1The and must come from the same Freestyle account. Snapshot ids from other accounts will fail to boot.
FREESTYLE_API_KEYFREESTYLE_SANDBOX_SNAPSHOTFor ad-hoc smoke testing:
bash
npx -y freestyle vm create --snapshot <snapshotId> --sshInside the VM, confirm everything baked correctly:
bash
cmuxd-remote version
cmux --help
claude --version
codex --version
node --version
bun --version脚本打印快照ID后,向用户提供cmux后端所需的环境变量块:
bash
FREESTYLE_API_KEY=fk_...
FREESTYLE_SANDBOX_SNAPSHOT=sh-xxxxxxxxxxxxxxxxxxxx
CMUX_VM_DEFAULT_PROVIDER=freestyle
CMUX_VM_FREESTYLE_ENABLED=1FREESTYLE_API_KEYFREESTYLE_SANDBOX_SNAPSHOT用于临时冒烟测试:
bash
npx -y freestyle vm create --snapshot <snapshotId> --ssh在VM内,确认所有组件已正确安装:
bash
cmuxd-remote version
cmux --help
claude --version
codex --version
node --version
bun --versionIterating on the repo
仓库迭代开发
The whole builder is one TypeScript file at . When updating it, keep it in lockstep with the source of truth in :
scripts/build-snapshot.tsrepo/web/scripts/build-cloud-vm-images.ts- Pinned agent CLI versions ().
CLOUD_AGENT_TOOLS - Default Node major and Bun version.
- Dockerfile body (,
freestyleBaseDockerfileContent,pythonOpenSSLCommands,toolInstallCommands,rootSetupCommands).imageSmokeTestCommands - Snapshot create call shape and recovery behavior ().
waitForFreestyleSnapshotByName
When cmux changes any of those, bump the matching constant in , ship a release, and update the cmux release tag the script defaults to if anything in the URL/checksum contract changes.
cmux-freestyleThe Freestyle CLI () covers VM create / list / ssh / exec / delete but does not expose snapshot create. That's why this script uses the SDK directly. Do not try to replace it with a CLI-only shell script.
npx -y freestyle vm ...freestyle整个构建器是位于的单个TypeScript文件。更新该文件时,需与仓库内的权威来源保持同步:
scripts/build-snapshot.tsrepo/web/scripts/build-cloud-vm-images.ts- 固定的Agent CLI版本()。
CLOUD_AGENT_TOOLS - 默认的Node主版本和Bun版本。
- Dockerfile内容(、
freestyleBaseDockerfileContent、pythonOpenSSLCommands、toolInstallCommands、rootSetupCommands)。imageSmokeTestCommands - 快照创建调用格式和恢复行为()。
waitForFreestyleSnapshotByName
当cmux修改上述任何内容时,需在中更新对应的常量,发布新版本,并在URL/校验和协议发生变化时更新脚本默认使用的cmux版本标签。
cmux-freestyleFreestyle CLI()支持VM的创建/列表/SSH/执行/删除,但不支持快照创建。这也是本脚本直接使用 SDK的原因。请勿尝试用仅基于CLI的Shell脚本替代它。
npx -y freestyle vm ...freestyleRules
规则
- Do not promise users that a shared snapshot id will work for them. It will not. Every user runs once with their own Freestyle API key.
./setup.sh - Do not bake provider API keys, R2 credentials, or anything user-specific into the snapshot. The Dockerfile must stay reproducible from public inputs only.
- Do not point the snapshot at an unreleased cmuxd-remote. Use a published release tag so SHA-256 verification has something to anchor on.
manaflow-ai/cmux - Do not loosen the agent CLI version policy. Specs must be exact semver pins; ranges and are rejected on purpose so each rebuild is reproducible.
latest - Do not run this against the manaflow Freestyle account when iterating. Use a personal Freestyle account; manaflow's snapshot lifecycle is managed by the in-repo builder and the cmux image manifest.
- 不要向用户承诺共享快照ID对他们有效。事实并非如此。每个用户都必须使用自己的Freestyle API密钥运行一次。
./setup.sh - 不要将提供商API密钥、R2凭据或任何用户特定内容嵌入快照。Dockerfile必须仅能通过公开输入重现。
- 不要将快照指向未发布的cmuxd-remote版本。请使用已发布的版本标签,以便SHA-256验证有可靠的锚点。
manaflow-ai/cmux - 不要放宽Agent CLI版本策略。必须指定精确的语义化版本;故意拒绝版本范围和,确保每次重建都可重现。
latest - 迭代开发时,不要针对manaflow的Freestyle账户运行本脚本。请使用个人Freestyle账户;manaflow的快照生命周期由仓库内的构建工具和cmux镜像清单管理。