cmux-freestyle

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

cmux 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,
manaflow-ai/cmux-freestyle
, so anyone with a Freestyle API key can run one shell script and get back a
FREESTYLE_SANDBOX_SNAPSHOT
id.
Freestyle 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
FREESTYLE_API_KEY
. There is no shortcut.
当用户需要一个可供cmux后端启动Cloud VM的Freestyle VM快照时,可使用本技能。它托管在独立的公开仓库
manaflow-ai/cmux-freestyle
中,因此任何拥有Freestyle API密钥的用户只需运行一个Shell脚本,即可获得一个
FREESTYLE_SANDBOX_SNAPSHOT
ID。
Freestyle快照的作用范围仅限于创建它的账户。来自manaflow账户或其他任何用户的快照ID,无法在其他Freestyle账户中使用。每个用户都必须使用自己的
FREESTYLE_API_KEY
运行设置脚本,没有捷径可走。

When 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 (
    cmux-freestyle
    ) instead of the in-repo builder at
    repo/web/scripts/build-cloud-vm-images.ts
    .
For internal cmux development that pushes a new snapshot to manaflow's Freestyle account and updates
repo/web/services/vms/images/manifest.json
, keep using
repo/web/scripts/build-cloud-vm-images.ts
. This skill is the external-user path.
  • 用户询问如何将自己的cmux指向Freestyle。
  • 用户自托管cmux Web后端,需要一个固定到已知cmux版本的快照。
  • 用户希望在自己的Freestyle账户上重新构建cmux Cloud VM镜像。
  • 用户希望对独立仓库(
    cmux-freestyle
    )进行迭代开发,而非使用仓库内的构建工具
    repo/web/scripts/build-cloud-vm-images.ts
对于将新快照推送到manaflow的Freestyle账户并更新
repo/web/services/vms/images/manifest.json
的内部cmux开发工作,请继续使用
repo/web/scripts/build-cloud-vm-images.ts
。本技能面向外部用户提供操作路径。

What it builds

构建内容

A Freestyle snapshot from a
Dockerfile
that mirrors
freestyleBaseDockerfileContent
in the in-repo builder:
  • ubuntu:24.04
    ,
    C.UTF-8
    , the same shell package set, the Python/OpenSSL shim required by the cmux browser proxy.
  • cmuxd-remote
    Linux/amd64 downloaded from a pinned
    manaflow-ai/cmux
    GitHub release, SHA-256 verified during the image build against
    cmuxd-remote-checksums.txt
    .
  • /usr/local/bin/cmux
    symlinked to
    cmuxd-remote
    .
  • Node.js, Bun, plus pinned coding agent CLIs (Claude Code, OpenCode, Codex, Pi).
  • Linux user
    cmux
    with passwordless sudo.
  • Systemd unit
    cmuxd-ws.service
    running
    cmuxd-remote serve --ws --listen 0.0.0.0:7777 --auth-lease-file ... --rpc-auth-lease-file ...
    on Freestyle port
    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.
基于
Dockerfile
构建Freestyle快照,该文件与仓库内构建工具中的
freestyleBaseDockerfileContent
保持一致:
  • 基础镜像为
    ubuntu:24.04
    ,字符编码为
    C.UTF-8
    ,包含相同的Shell软件包集,以及cmux浏览器代理所需的Python/OpenSSL垫片。
  • 从固定的
    manaflow-ai/cmux
    GitHub版本下载
    cmuxd-remote
    Linux/amd64版本,在镜像构建过程中通过
    cmuxd-remote-checksums.txt
    进行SHA-256验证。
  • /usr/local/bin/cmux
    软链接至
    cmuxd-remote
  • 预装Node.js、Bun,以及固定版本的编码Agent CLI(Claude Code、OpenCode、Codex、Pi)。
  • 创建Linux用户
    cmux
    ,拥有免密码sudo权限。
  • 配置Systemd单元
    cmuxd-ws.service
    ,运行
    cmuxd-remote serve --ws --listen 0.0.0.0:7777 --auth-lease-file ... --rpc-auth-lease-file ...
    ,并将Freestyle端口
    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.sh
Or the one-liner:
bash
FREESTYLE_API_KEY=fk_... \
  curl -fsSL https://raw.githubusercontent.com/manaflow-ai/cmux-freestyle/main/install.sh | bash
Useful flags / env on
./setup.sh snapshot
(the default subcommand):
  • --release <tag>
    or
    CMUX_RELEASE_TAG=<tag>
    pins the cmuxd-remote release. Default is the latest stable
    manaflow-ai/cmux
    release.
  • --name <name>
    or
    CMUX_FREESTYLE_SNAPSHOT_NAME
    sets the Freestyle snapshot name.
  • --skip-cache
    or
    CMUX_FREESTYLE_SKIP_CACHE=1
    forces a clean Freestyle rebuild.
  • --codex-spec none
    ,
    --claude-spec none
    , etc. drop individual agent CLIs.
  • --json
    emits a machine-readable result; the human path prints
    FREESTYLE_SANDBOX_SNAPSHOT=sh-...
    at the end.
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>
    CMUX_RELEASE_TAG=<tag>
    :固定cmuxd-remote的版本。默认使用
    manaflow-ai/cmux
    的最新稳定版本。
  • --name <name>
    CMUX_FREESTYLE_SNAPSHOT_NAME
    :设置Freestyle快照的名称。
  • --skip-cache
    CMUX_FREESTYLE_SKIP_CACHE=1
    :强制Freestyle进行干净重建。
  • --codex-spec none
    --claude-spec none
    等:移除单个Agent CLI。
  • --json
    :输出机器可读的结果;面向用户的路径会在最后打印
    FREESTYLE_SANDBOX_SNAPSHOT=sh-...
构建时长取决于Freestyle的层缓存,通常为5至15分钟。

Full self-host bundle

完整自托管包

./setup.sh
is a dispatcher with four subcommands. Use them together when a user wants more than just the snapshot id:
bash
./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 view
web
is the Next.js dev env bootstrap: it clones
manaflow-ai/cmux
to
~/cmux-freestyle-cmux
, writes the Freestyle + Cloud VM env keys into
web/.env.local
, runs
bun install
, and brings up the per-worktree Docker Postgres unless
--no-postgres
is set. Stack Auth keys (
STACK_SECRET_SERVER_KEY
,
NEXT_PUBLIC_STACK_PROJECT_ID
,
NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY
) are honoured if exported but optional. The script only needs
git
and
bun
(plus
docker
for Postgres).
home
is the "headquarters view": it installs and prepares the Ink/TypeScript port of
cmux-home
at
~/cmux-freestyle-home/ink
. The TUI connects to the local cmux app's Unix socket and gives end users a Node-only dashboard of every workspace plus a Codex/Claude composer. The Ink port currently lives on the
feat-ink-rewrite
branch; switch the default
--ref
once it merges to
main
. The Rust crate at the cmux-home repo root remains the full-featured upstream.
If
FREESTYLE_API_KEY
is set in the env when
bun dev
runs (the
home
script exports it from the user's
~/.secrets/cmux.env
and the shell), cmux-home renders a second panel under the workspace list titled
Freestyle VMs (N)
. Each row shows the VM id, state, snapshot id (the one from
./setup.sh snapshot
), 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.
Selecting a VM enables the following actions on the row:
  • enter
    opens the sandbox workflow: creates a new cmux workspace running
    freestyle-vm-ssh <vmId>
    . The helper script mints a short-lived Freestyle SSH identity, opens an SSH session through
    vm-ssh.freestyle.sh
    with
    -R 31415:127.0.0.1:31415
    (reverse-forward to the local Subrouter AI gateway on
    127.0.0.1:31415
    ) plus
    -L
    forwards for common dev ports (
    3000
    ,
    5173
    ,
    8000
    ,
    8080
    ), writes a
    ~/.codex/config.toml
    inside the VM that points
    openai_base_url
    at 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 at
    http://127.0.0.1:3000
    .
  • ctrl+o
    opens the local-codex workflow: a normal cmux workspace at the TUI's
    --cwd
    , no SSH, plus a browser pane on the right at
    https://<vmId>.vm.freestyle.sh
    . Codex/Claude run on the mac against the local checkout; the VM is treated as a remote dev server.
  • ctrl+x
    destroys the VM through the Freestyle SDK.
  • ctrl+n
    on the
    Freestyle VMs (N)
    header creates a new VM from
    FREESTYLE_SANDBOX_SNAPSHOT
    .
Freestyle gateway constraint. The Freestyle SSH gateway at
vm-ssh.freestyle.sh
rejects
-R
remote port forwarding (
remote port forwarding failed for listen port 31415
). The
--reverse-subrouter
flag is therefore opt-in and works only for ordinary Linux/macOS sshd hosts.
Default path for codex inside a Freestyle VM (works today):
freestyle-vm-ssh
mints an ephemeral preauth Tailscale key via
tsadmin api POST /tailnet/-/keys
(tag
tag:server
, expires in 1h), runs
tailscale up
inside the VM under userspace networking (
--tun=userspace-networking
), enables tailscaled's HTTP proxy + SOCKS5 server on
127.0.0.1:1055
, writes
/etc/profile.d/cmux-tailnet-proxy.sh
so every login shell exports
HTTP_PROXY
/
HTTPS_PROXY
/
NO_PROXY
, and writes
~/.codex/config.toml
with
openai_base_url = "http://subrouter-team.tail41290.ts.net:31415/v1"
. Codex inside the VM then connects to the existing
subrouter-team
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
tailscale
package, so first-time bring-up is ~6 s end-to-end; subsequent sessions reuse the existing state.
Disable per-call with
--no-tailscale
, override the subrouter URL with
--subrouter-url <url>
or
SUBROUTER_REMOTE_URL
, override the auth-key with
--tailscale-authkey <key>
or
TAILSCALE_AUTHKEY
. Today Subrouter only routes Codex, so use Codex inside the VM until Subrouter adds Claude/OpenCode support.
Helper requires
sshpass
on the mac (
brew install hudochenkov/sshpass/sshpass
) and
tsadmin
on
PATH
(
skills/tsadmin/scripts/tsadmin
).
./setup.sh
是一个调度器,包含四个子命令。当用户需要的不仅仅是快照ID时,可以组合使用这些命令:
bash
./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)主控视图
web
子命令用于引导Next.js开发环境:它会将
manaflow-ai/cmux
克隆到
~/cmux-freestyle-cmux
,将Freestyle + Cloud VM环境密钥写入
web/.env.local
,运行
bun install
,并启动每个工作树的Docker Postgres(除非设置了
--no-postgres
)。如果已导出Stack Auth密钥(
STACK_SECRET_SERVER_KEY
NEXT_PUBLIC_STACK_PROJECT_ID
NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY
),脚本会予以识别,但这并非必需。该脚本仅需要
git
bun
(若使用Postgres则还需要
docker
)。
home
子命令用于设置“主控视图”:它会在
~/cmux-freestyle-home/ink
安装并准备
cmux-home
的Ink/TypeScript端口。该TUI会连接到本地cmux应用的Unix套接字,为终端用户提供一个仅基于Node的所有工作区仪表板,以及Codex/Claude编辑器。目前Ink端口位于
feat-ink-rewrite
分支;当该分支合并到
main
后,需切换默认的
--ref
参数。cmux-home仓库根目录下的Rust crate仍是功能完整的上游版本。
如果
bun dev
运行时环境中设置了
FREESTYLE_API_KEY
home
脚本会从用户的
~/.secrets/cmux.env
和Shell中导出该变量),cmux-home会在工作区列表下方显示第二个面板,标题为
Freestyle VMs (N)
。每一行会显示VM ID、状态、快照ID(来自
./setup.sh snapshot
)和运行时长。这使得TUI成为本地cmux工作区和用户Freestyle Cloud VM的统一仪表板,同一个选择光标可在两个面板间切换。
选择一个VM后,可在该行执行以下操作:
  • enter
    :打开沙箱工作流:创建一个新的cmux工作区,运行
    freestyle-vm-ssh <vmId>
    。该辅助脚本会生成一个短期的Freestyle SSH身份,通过
    vm-ssh.freestyle.sh
    打开SSH会话,参数包含
    -R 31415:127.0.0.1:31415
    (反向转发到本地Subrouter AI网关的
    127.0.0.1:31415
    )以及针对常见开发端口(
    3000
    5173
    8000
    8080
    )的
    -L
    转发,在VM内写入
    ~/.codex/config.toml
    ,将
    openai_base_url
    指向转发后的subrouter,然后进入登录Shell。在该Shell中启动的Codex会通过用户Mac上的Subrouter进行路由。同时会在右侧打开浏览器窗口,指向
    http://127.0.0.1:3000
  • ctrl+o
    :打开local-codex工作流:在TUI的
    --cwd
    路径创建一个普通的cmux工作区,无需SSH,同时在右侧打开浏览器窗口,指向
    https://<vmId>.vm.freestyle.sh
    。Codex/Claude在Mac上针对本地检出的代码运行;VM被视为远程开发服务器。
  • ctrl+x
    :通过Freestyle SDK销毁VM。
  • Freestyle VMs (N)
    标题上按
    ctrl+n
    :从
    FREESTYLE_SANDBOX_SNAPSHOT
    创建新的VM。
Freestyle网关限制:位于
vm-ssh.freestyle.sh
的Freestyle SSH网关会拒绝
-R
远程端口转发(提示
remote port forwarding failed for listen port 31415
)。因此
--reverse-subrouter
标志为可选启用,且仅适用于普通Linux/macOS sshd主机。
Freestyle VM内Codex的默认路径(当前可用)
freestyle-vm-ssh
通过
tsadmin api POST /tailnet/-/keys
生成一个临时的预授权Tailscale密钥(标签
tag:server
,1小时后过期),在VM内以用户空间网络模式(
--tun=userspace-networking
)运行
tailscale up
,在
127.0.0.1:1055
启用tailscaled的HTTP代理+SOCKS5服务器,写入
/etc/profile.d/cmux-tailnet-proxy.sh
,使每个登录Shell都导出
HTTP_PROXY
/
HTTPS_PROXY
/
NO_PROXY
,并写入
~/.codex/config.toml
,设置
openai_base_url = "http://subrouter-team.tail41290.ts.net:31415/v1"
。VM内的Codex随后会通过本地代理连接到tailnet上现有的
subrouter-team
主机,因此所有OpenAI流量都会通过Subrouter的账户调度进行路由。cmux-freestyle快照已预装apt
tailscale
包,首次启动耗时约6秒;后续会话会重用现有状态。
可通过
--no-tailscale
禁用该功能,通过
--subrouter-url <url>
SUBROUTER_REMOTE_URL
覆盖subrouter URL,通过
--tailscale-authkey <key>
TAILSCALE_AUTHKEY
覆盖授权密钥。目前Subrouter仅支持Codex路由,因此在Subrouter添加Claude/OpenCode支持前,请在VM内使用Codex。
该辅助工具需要Mac上安装
sshpass
brew install hudochenkov/sshpass/sshpass
),且
tsadmin
需在
PATH
中(
skills/tsadmin/scripts/tsadmin
)。

GitHub auth

GitHub认证

The snapshot builder talks only to public GitHub endpoints (
/repos/manaflow-ai/cmux/releases/latest
and the release-asset
cmuxd-remote-checksums.txt
). 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
GITHUB_TOKEN
(or
GH_TOKEN
) and the script forwards it on both the API call and the checksums download. Mention this when guiding a CI integration.
The Freestyle SDK only needs
FREESTYLE_API_KEY
; no GitHub credentials are required for snapshot creation.
setup.sh web
clones
manaflow-ai/cmux
anonymously, so no auth is required there either; only suggest
gh auth login
if a user explicitly wants
git push
against their own fork.
快照构建器仅与公开的GitHub端点通信(
/repos/manaflow-ai/cmux/releases/latest
和发布资产
cmuxd-remote-checksums.txt
)。未认证的GitHub API每小时允许60次请求,正常使用下完全足够。如果用户遇到403/429错误(共享IP、CI循环、重复重建),应设置
GITHUB_TOKEN
(或
GH_TOKEN
),脚本会在API调用和校验和下载时自动使用该令牌。在指导CI集成时需提及这一点。
Freestyle SDK仅需要
FREESTYLE_API_KEY
;创建快照无需GitHub凭据。
setup.sh web
会匿名克隆
manaflow-ai/cmux
,因此也不需要认证;仅当用户明确需要向自己的分支执行
git push
时,才建议使用
gh auth login

Plugging 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=1
The
FREESTYLE_API_KEY
and
FREESTYLE_SANDBOX_SNAPSHOT
must come from the same Freestyle account. Snapshot ids from other accounts will fail to boot.
For ad-hoc smoke testing:
bash
npx -y freestyle vm create --snapshot <snapshotId> --ssh
Inside 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=1
FREESTYLE_API_KEY
FREESTYLE_SANDBOX_SNAPSHOT
必须来自同一个Freestyle账户。来自其他账户的快照ID无法启动VM。
用于临时冒烟测试:
bash
npx -y freestyle vm create --snapshot <snapshotId> --ssh
在VM内,确认所有组件已正确安装:
bash
cmuxd-remote version
cmux --help
claude --version
codex --version
node --version
bun --version

Iterating on the repo

仓库迭代开发

The whole builder is one TypeScript file at
scripts/build-snapshot.ts
. When updating it, keep it in lockstep with the source of truth in
repo/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
cmux-freestyle
, ship a release, and update the cmux release tag the script defaults to if anything in the URL/checksum contract changes.
The Freestyle CLI (
npx -y freestyle vm ...
) covers VM create / list / ssh / exec / delete but does not expose snapshot create. That's why this script uses the
freestyle
SDK directly. Do not try to replace it with a CLI-only shell script.
整个构建器是位于
scripts/build-snapshot.ts
的单个TypeScript文件。更新该文件时,需与仓库内的权威来源
repo/web/scripts/build-cloud-vm-images.ts
保持同步:
  • 固定的Agent CLI版本(
    CLOUD_AGENT_TOOLS
    )。
  • 默认的Node主版本和Bun版本。
  • Dockerfile内容(
    freestyleBaseDockerfileContent
    pythonOpenSSLCommands
    toolInstallCommands
    rootSetupCommands
    imageSmokeTestCommands
    )。
  • 快照创建调用格式和恢复行为(
    waitForFreestyleSnapshotByName
    )。
当cmux修改上述任何内容时,需在
cmux-freestyle
中更新对应的常量,发布新版本,并在URL/校验和协议发生变化时更新脚本默认使用的cmux版本标签。
Freestyle CLI(
npx -y freestyle vm ...
)支持VM的创建/列表/SSH/执行/删除,但不支持快照创建。这也是本脚本直接使用
freestyle
SDK的原因。请勿尝试用仅基于CLI的Shell脚本替代它。

Rules

规则

  • Do not promise users that a shared snapshot id will work for them. It will not. Every user runs
    ./setup.sh
    once with their own Freestyle API key.
  • 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
    manaflow-ai/cmux
    release tag so SHA-256 verification has something to anchor on.
  • Do not loosen the agent CLI version policy. Specs must be exact semver pins; ranges and
    latest
    are rejected on purpose so each rebuild is reproducible.
  • 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版本。请使用已发布的
    manaflow-ai/cmux
    版本标签,以便SHA-256验证有可靠的锚点。
  • 不要放宽Agent CLI版本策略。必须指定精确的语义化版本;故意拒绝版本范围和
    latest
    ,确保每次重建都可重现。
  • 迭代开发时,不要针对manaflow的Freestyle账户运行本脚本。请使用个人Freestyle账户;manaflow的快照生命周期由仓库内的构建工具和cmux镜像清单管理。