devboxes
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseNamespace devboxes
Namespace devboxes
Namespace devboxes are remote or machines. Linux devboxes have Docker available. This skill describes the general building blocks for working with devboxes - creating them, transferring files, hydrating a workspace, installing toolchains, running commands with , sharing web work with teammates through , and managing the devbox lifecycle.
linux/amd64macos/arm64devbox execdevbox.soThroughout this skill:
- devbox - a Namespace machine, identified by its .
name - - the devbox name passed to all
<name>subcommands.devbox
The devbox may be long-lived, reused across tasks, or torn down immediately depending on the caller's intent. Pass at creation time to mark it as disposable.
--ephemeralFor run-once-then-destroy workflows (single-script or test runs, optional sharding), see references/run-tests.md.
Namespace devboxes 是远程的 或 机器。Linux devbox 自带 Docker。本 skill 描述使用 devbox 的基础模块:创建它们、传输文件、加载(hydrate)工作区、安装工具链、使用 运行命令、通过 与队友共享 Web 工作,以及管理 devbox 生命周期。
linux/amd64macos/arm64devbox execdevbox.so在整个 skill 中:
- devbox - 一台 Namespace 机器,由其 标识。
name - - 传递给所有
<name>子命令的 devbox 名称。devbox
devbox 可以是长期存活、跨任务复用,也可以根据调用者的意图立即销毁。在创建时传入 将其标记为可丢弃。
--ephemeral对于“运行一次即销毁”的工作流(单脚本或测试运行、可选的分片),请参阅 references/run-tests.md。
0. Establish where you are running
0. 确定你正在哪里运行
Everything below assumes you are driving a devbox from somewhere else. First check whether you
are already ON one - the tooling and the auth story are different:
bash
[ -n "${NAMESPACE_DEVBOX_WORKSPACE_DIR:-}" ] && echo "on a devbox"The Devbox agent injects that variable into every process on the machine, so it is a reliable
one-line check. If it is set, read references/inside-a-devbox.md
before doing anything else. Two things are different there:
- Ordinary commands need no wrapper. You are on the machine. Run ,
go testand file edits directly, and skip thegitpreflight below for work scoped to the devbox you are in.devbox - Both CLIs are already usable - do not run .
devbox loginandboxctlboth ship indevbox. The~/.devbox/binCLI is authenticated by a workload credential, which acts as the tenant rather than as a person: it can drive workspace-access devboxes, but not ones private to their creator - including, usually, the machine you are on. That is whydevbox, which reaches the local agent over a socket and needs no credential, is the tool for the current devbox rather than merely the quicker one. Bewareboxctlhere: it reports "Not logged in" even while the CLI works, and acting on that leads to a browser login flow you cannot complete. The reference covers the rest, includingdevbox auth check-loginfor creating sibling boxes.--access_mode workspace
Preflight Resolve from PATH or its platform's default install location; use the absolute path if PATH is stale, and install the Devbox CLI yourself only if it is absent. Run the resolved CLI's ; if login is required, run , let the user complete the browser flow, and wait for the command to return. See references/cli-setup.md for exact steps, including session expiry and workspace switching. Do not try to mint or borrow credentials from other tooling.
devboxauth check-logindevbox login以下所有内容都假定你是从其他位置驱动 devbox 的。首先检查你是否已经在某个 devbox 内部——此时的工具和认证方式有所不同:
bash
[ -n "${NAMESPACE_DEVBOX_WORKSPACE_DIR:-}" ] && echo "on a devbox"Devbox agent 会将该变量注入机器上的每个进程,因此这是一个可靠的一行检查。如果该变量已设置,请在做任何其他事情之前阅读 references/inside-a-devbox.md。在这里有两件事不同:
- 普通命令不需要任何包装。 你就在机器上。直接运行 、
go test和文件编辑,并跳过下面的git预检,前提是工作范围限定于你所在的 devbox。devbox - 两个 CLI 都已可用——不要运行 。
devbox login和boxctl都位于devbox中。~/.devbox/binCLI 使用 workload 凭据进行认证,它以租户身份而非个人身份运作:它可以驱动 workspace 访问级别的 devbox,但不能驱动对其创建者私有的 devbox——通常包括你当前所在的这台机器。这就是为什么devbox(通过 socket 访问本地 agent,且不需要凭据)是操作当前 devbox 的工具,而不仅仅是因为它更快。注意这里的boxctl:即使 CLI 能正常工作,它也会报告“Not logged in”,如果据此操作,会进入一个你无法完成的浏览器登录流程。其余内容(包括用于创建兄弟 box 的devbox auth check-login)由该 reference 文档说明。--access_mode workspace
预检 从 PATH 或平台默认安装位置解析 ;如果 PATH 过期,请使用绝对路径;只有在缺失时才自行安装 Devbox CLI。运行解析出的 CLI 的 ;如果需要登录,运行 ,让用户完成浏览器流程,并等待命令返回。具体步骤(包括会话过期和 workspace 切换)见 references/cli-setup.md。不要尝试从其他工具生成或借用凭据。
devboxauth check-logindevbox login1. Create a devbox
1. 创建 devbox
If the task needs a project toolchain (Go, Node, Xcode, etc.), pick an image that already includes it to avoid reinstalling dependencies on every run: run ONCE to discover existing project images, and use one if it fits. Cache that result - repeating the call does not tell you anything new.
devbox image list -o jsonSkip image discovery entirely for scratch work that needs no project toolchain (a one-off command, a throwaway VM, a quick platform check) and go straight to . On Linux, already ships common toolchains - Go, for instance - so for many tasks it is the whole answer. For simpler Linux cases generally, fall back to and install dependencies directly.
builtin:defaultbuiltin:defaultbuiltin:defaultImportant Pass the short field from to (e.g. or ), not the full URL - full references typically fail. Ensure the image matches the requested platform.
namedevbox image list -o json--image<org>/<image>builtin:defaultrepositorybash
devbox create \
--name <name> \
[--platform <linux/amd64|macos/arm64>] \
--image <image> \
--size <size> \
[--ephemeral] \
[--checkout <repo-url>] \
--purpose "<purpose>"Linux/amd64 is the default when is omitted. Pass when the task requires macOS or Apple Silicon.
--platform--platform macos/arm64Add when the devbox does not need to persist after a task is complete; omit it when persistence is required.
--ephemeralImportant (workspace checkout default) If is unset, Namespace uses the workspace's configured default repo and clones it automatically. When no repository is needed (e.g. a scratch VM for a one-off command), pass to skip cloning entirely.
--checkout--no_checkout--checkout <repo-url>git@github.com:org/repo.git/workspaces/<repo-name>- Expire the just-created devbox () to free capacity.
devbox expire <name> --force - If is installed locally, recreate the devbox WITHOUT
gh, then run--checkoutto forward yourdevbox setup-github <name>token into the devbox. Once that succeeds, runghinside the devbox viagit clone --depth=1 <repo-url> /workspaces/<repo-name>. Always usedevbox exec <name> --for large monorepos - full clones can run for minutes with sparse progress output and look identical to a hang. Important The forwarded--depth=1token authenticates HTTPS only - clone viagh, nothttps://github.com/<org>/<repo>.git.git@github.com:... - If is not installed, or
gh/ the in-devboxdevbox setup-githubfails, instruct the user to link their GitHub organization to Namespace at https://cloud.namespace.so/workspace/workspace/integrations?integration=github - checkout cannot proceed without it.git clone
Important (case-sensitive org slug) The Namespace association lookup is case-sensitive on the GitHub org/owner segment of . Use the org/owner casing EXACTLY as it appears in the repo URL the user gave you (or as returned by ). NEVER try alternative casings (e.g. lowercasing the org) as a "fix" when checkout fails.
--checkoutgit remote -vLinux sizes: (4 vCPU / 8 GB), (8 vCPU / 16 GB), (16 vCPU / 32 GB), (32 vCPU / 64 GB). macOS sizes: (6 vCPU / 14 GB) and (12 vCPU / 28 GB). Use the smallest size only for narrow commands or small targeted workloads; prefer bigger when the workload has large dependencies or builds multiple packages, to avoid OOM. If a process is killed with , upgrade to a larger size and retry.
smlxlmlsignal: killedOverlap creation with local prep blocks until the machine is ready, which takes tens of seconds. Use that time: run as a background task, then immediately compute any local git diff and write the setup and run scripts locally. Once creation completes, upload and execute. This eliminates idle waiting.
devbox createdevbox createNote Devbox creation might fail due to Namespace plan limits on resource tiers or instance counts. If this happens: PROMPT THE USER BEFORE PROCEEDING run and ask to expire or reuse any of the available devboxes, then retry; As a last resort, consolidate work across fewer devboxes rather than blocking.
devbox listFor test or script runs that benefit from sharding across multiple devboxes, see references/run-tests.md.
如果任务需要项目工具链(Go、Node、Xcode 等),选择一个已经包含该工具链的镜像,以避免每次运行都重新安装依赖:只运行一次 来发现现有的项目镜像,如果合适就使用它。缓存该结果——重复调用不会带来任何新信息。
devbox image list -o json对于不需要项目工具链的临时工作(一次性命令、一次性 VM、快速平台检查),完全跳过镜像发现,直接使用 。在 Linux 上, 已经自带常用工具链——例如 Go——所以对许多任务来说它就是完整答案。对于更简单的 Linux 场景,通常回退到 并直接安装依赖。
builtin:defaultbuiltin:defaultbuiltin:default重要 将 中的短 字段传给 (例如 或 ),而不是完整的 URL——完整引用通常会失败。确保镜像与请求的平台匹配。
devbox image list -o jsonname--image<org>/<image>builtin:defaultrepositorybash
devbox create \
--name <name> \
[--platform <linux/amd64|macos/arm64>] \
--image <image> \
--size <size> \
[--ephemeral] \
[--checkout <repo-url>] \
--purpose "<purpose>"省略 时,默认是 。当任务需要 macOS 或 Apple Silicon 时,传入 。
--platformlinux/amd64--platform macos/arm64当 devbox 在任务完成后无需保留时,添加 ;需要持久化时省略它。
--ephemeral重要(workspace checkout 默认行为) 如果未设置 ,Namespace 会使用 workspace 配置的默认仓库并自动克隆它。当不需要任何仓库时(例如用于一次性命令的临时 VM),传入 以完全跳过克隆。
--checkout--no_checkout--checkout <repo-url>git@github.com:org/repo.git/workspaces/<repo-name>- 销毁刚创建的 devbox()以释放容量。
devbox expire <name> --force - 如果本地安装了 ,在不带
gh的情况下重新创建 devbox,然后运行--checkout将你的devbox setup-github <name>token 转发到 devbox。成功后,通过gh在 devbox 内运行devbox exec <name> --。对于大型 monorepo,始终使用git clone --depth=1 <repo-url> /workspaces/<repo-name>——完整克隆可能运行数分钟且进度输出稀疏,看起来与卡死无异。重要 转发的--depth=1token 仅支持 HTTPS 认证——请通过gh克隆,而不是https://github.com/<org>/<repo>.git。git@github.com:... - 如果未安装 ,或者
gh/ devbox 内的devbox setup-github失败,指示用户将其 GitHub 组织关联到 Namespace:https://cloud.namespace.so/workspace/workspace/integrations?integration=github - 没有此关联,checkout 无法继续。git clone
重要(组织 slug 区分大小写) Namespace 对 的 GitHub org/owner 段的关联查询区分大小写。请使用用户给你的仓库 URL 中出现的 org/owner 大小写(或 返回的大小写)完全一致。当 checkout 失败时,绝不要尝试其他大小写形式(例如将组织名小写)作为“修复”。
--checkoutgit remote -vLinux 规格:(4 vCPU / 8 GB)、(8 vCPU / 16 GB)、(16 vCPU / 32 GB)、(32 vCPU / 64 GB)。macOS 规格:(6 vCPU / 14 GB)和 (12 vCPU / 28 GB)。只在狭窄命令或小型定向工作负载时使用最小规格;当工作负载具有大量依赖或构建多个包时,优先使用更大规格,以避免 OOM。如果进程因 被终止,升级到更大规格并重试。
smlxlmlsignal: killed将创建过程与本地准备工作重叠 会阻塞直到机器就绪,这需要数十秒。利用这段时间:将 作为后台任务运行,然后立即计算本地 git diff,并在本地编写 setup 和 run 脚本。创建完成后,上传并执行。这样可以消除空闲等待。
devbox createdevbox create注意 devbox 创建可能因 Namespace 套餐对资源层级或实例数量的限制而失败。如果发生这种情况:在继续之前提示用户 运行 ,询问是否可以过期或复用任何可用 devbox,然后重试;作为最后手段,将工作合并到更少的 devbox 上,而不是阻塞。
devbox list对于适合跨多个 devbox 分片的测试或脚本运行,请参阅 references/run-tests.md。
2. Hydrate the workspace and install toolchains
2. 加载工作区(hydrate)并安装工具链
Upload and download files
上传和下载文件
bash
devbox upload <name> <local-path> <remote-path> [--mkdir]
devbox download <name> <remote-path> <local-path>- MUST be a full file path. A trailing
<remote-path>fails./ - creates missing parent directories; it does NOT make the target a directory.
--mkdir - The executable bit is NOT preserved. Run with
chmod +xafter uploading scripts.devbox exec - Write under or
/workspaces. The remote user is unprivileged ($HOME, uid 1001), not root, so an upload to a system path fails on the parent directory -devbox- andmkdir: cannot create directory '/srv/www': Permission deniedcannot rescue it, because the problem is permission, not absence. Serving a page?--mkdiris the natural home, not/workspaces/<name>/or/srv./var/www
bash
devbox upload <name> <local-path> <remote-path> [--mkdir]
devbox download <name> <remote-path> <local-path>- 必须是完整文件路径。以
<remote-path>结尾会失败。/ - 会创建缺失的父目录;它不会把目标变成目录。
--mkdir - 可执行位不会被保留。上传脚本后,请使用 运行
devbox exec。chmod +x - 写入 或
/workspaces之下。 远程用户是非特权用户($HOME,uid 1001),不是 root,因此上传到系统路径会在父目录处失败——devbox——而mkdir: cannot create directory '/srv/www': Permission denied无法解决,因为问题是权限而非目录不存在。要托管页面?--mkdir是自然的位置,而不是/workspaces/<name>/或/srv。/var/www
Hydrate the workspace
加载(hydrate)工作区
Namespace devboxes configured with a repo in the UI auto-clone it to on startup. Always check there first before syncing:
/workspaces/<repo-name>bash
devbox exec <name> -- ls /workspaces/If the repo is already present, use that path directly. The auto-cloned repo reflects the default branch, so it does NOT have your local work on it - you must get that across before running anything.
Pick the cheapest sync that covers your files. Two approaches, and the simple one is usually right:
(a) Default: ship the working tree. For a small or medium repo, copy the files as they are on disk. This captures tracked edits and untracked files in one step, needs no reasoning about commits or bases, and cannot silently omit anything. Upload a handful of files directly, or tar the tree for more:
bash
undefinedNamespace 在 UI 中配置了仓库的 devbox 会在启动时自动将其克隆到 。在同步之前,始终先在那里检查:
/workspaces/<repo-name>bash
devbox exec <name> -- ls /workspaces/如果仓库已存在,直接使用该路径。自动克隆的仓库反映默认分支,因此它并不包含你的本地工作——在运行任何东西之前,你必须先把本地工作同步过去。
选择覆盖你文件的最便宜的同步方式。 有两种方法,通常简单的那种就是正确的:
(a) 默认:传输工作树。 对于小型或中型仓库,直接复制磁盘上的文件。这会在一步之内捕获已跟踪的修改和未跟踪的文件,无需考虑提交或基线,也不会静默遗漏任何内容。直接上传少量文件;文件较多时对工作树打 tar 包:
bash
undefinedA few files - upload them directly.
A few files - upload them directly.
devbox upload <name> ./calc.go /workspaces/<repo-name>/calc.go --mkdir
devbox upload <name> ./calc.go /workspaces/<repo-name>/calc.go --mkdir
More than a handful - tar the tree, excluding .git and build output.
More than a handful - tar the tree, excluding .git and build output.
tar --exclude .git -czf /tmp/tree.tgz -C <repo-root> .
devbox upload <name> /tmp/tree.tgz /tmp/tree.tgz
devbox exec <name> -- mkdir -p /workspaces/<repo-name>
devbox exec <name> -- tar -xzf /tmp/tree.tgz -C /workspaces/<repo-name>
**(b) Large repo: align the commit, then patch.** Once the tree is big enough that copying it is slower than cloning it, let the devbox's own clone do the heavy lifting and send only a diff. This is strictly more machinery, so reach for it only when (a) is genuinely too slow.
**Important** The devbox clone is on the default branch, so the diff and the checkout MUST name the same commit or unrelated files get clobbered:
```bash
BASE=$(git merge-base origin/main HEAD)
git diff "$BASE" > /tmp/changes.patch # add --binary if the diff touches generated/binary filestar --exclude .git -czf /tmp/tree.tgz -C <repo-root> .
devbox upload <name> /tmp/tree.tgz /tmp/tree.tgz
devbox exec <name> -- mkdir -p /workspaces/<repo-name>
devbox exec <name> -- tar -xzf /tmp/tree.tgz -C /workspaces/<repo-name>
**(b) 大型仓库:对齐提交,然后打补丁。** 当工作树大到复制比克隆更慢时,让 devbox 自己的克隆完成繁重工作,只发送一个 diff。这明显需要更多机制,所以只有在 (a) 确实太慢时才使用。
**重要** devbox 的克隆位于默认分支,因此 diff 和 checkout 必须指向同一个提交,否则不相关的文件会被覆盖:
```bash
BASE=$(git merge-base origin/main HEAD)
git diff "$BASE" > /tmp/changes.patch # add --binary if the diff touches generated/binary filesFor git, prefer git -C <path>
over cd <path> && git ...
- no cwd to get wrong.
git -C <path>cd <path> && git ...For git, prefer git -C <path>
over cd <path> && git ...
- no cwd to get wrong.
git -C <path>cd <path> && git ...devbox exec <name> -- git -C /workspaces/<repo-name> fetch --depth=1 origin "$BASE"
devbox exec <name> -- git -C /workspaces/<repo-name> checkout "$BASE"
devbox upload <name> /tmp/changes.patch /tmp/changes.patch
devbox exec <name> -- git -C /workspaces/<repo-name> apply /tmp/changes.patch
devbox exec <name> -- git -C /workspaces/<repo-name> status --short
**Important (the failure mode that makes (b) risky)** `git diff` only covers TRACKED files. A brand-new file you have not `git add`ed is invisible to it, so a patch-based sync will quietly leave it behind - and if that file is a new test, you will confidently report a result from code that was never there. Requirement (b) is therefore incomplete on its own: send untracked files too.
```bash
git ls-files --others --exclude-standard # exactly what a patch will MISSUpload those directly, add them to the tarball, or rsync them if there are many:
bash
undefineddevbox exec <name> -- git -C /workspaces/<repo-name> fetch --depth=1 origin "$BASE"
devbox exec <name> -- git -C /workspaces/<repo-name> checkout "$BASE"
devbox upload <name> /tmp/changes.patch /tmp/changes.patch
devbox exec <name> -- git -C /workspaces/<repo-name> apply /tmp/changes.patch
devbox exec <name> -- git -C /workspaces/<repo-name> status --short
**重要(使 (b) 有风险的失败模式)** `git diff` 只覆盖已跟踪(TRACKED)文件。一个你尚未 `git add` 的全新文件对它不可见,因此基于补丁的同步会悄悄漏掉它——而如果该文件是一个新测试,你会自信地报告一个从来不在那里的代码产生的结果。因此,(b) 本身是不完整的:也要发送未跟踪的文件。
```bash
git ls-files --others --exclude-standard # exactly what a patch will MISS直接上传这些文件、将其加入 tar 包,如果有大量文件则使用 rsync:
bash
undefinedfor rsync - configure native ssh
for rsync - configure native ssh
devbox configure-ssh <name>
devbox configure-ssh <name>
After running this, you can connect with:
After running this, you can connect with:
ssh <name>.devbox.namespace
ssh <name>.devbox.namespace
Then list untracked files and feed them to rsync
Then list untracked files and feed them to rsync
git ls-files --others --exclude-standard |
rsync -av --files-from=- .
<name>.devbox.namespace:/workspaces/<repo-name>/
rsync -av --files-from=- .
<name>.devbox.namespace:/workspaces/<repo-name>/
**Verify before you trust a result.** Confirm the files you meant to send are actually there, so a sync gap surfaces now rather than as a wrong answer later:
```bash
devbox exec <name> -- ls -la /workspaces/<repo-name>If the repo has no remote at all (a scratch or local-only repo), (b) is not available - use (a).
git ls-files --others --exclude-standard |
rsync -av --files-from=- .
<name>.devbox.namespace:/workspaces/<repo-name>/
rsync -av --files-from=- .
<name>.devbox.namespace:/workspaces/<repo-name>/
**在信任结果之前先验证。** 确认你打算发送的文件确实存在,这样同步缺口会在当下暴露,而不是稍后变成一个错误答案:
```bash
devbox exec <name> -- ls -la /workspaces/<repo-name>如果仓库根本没有 remote(临时仓库或仅本地仓库),则 (b) 不可用——使用 (a)。
Install toolchains
安装工具链
If a tool is missing, install only what the workload needs.
Important Check whether a tool is already present before installing it - on Linux, ships more than you might expect, including languages such as Go. Try the command before reaching for a manual install.
builtin:defaultProbe with the tool's own flag, which is a real executable:
bash
devbox exec <name> -- go versioncommand -vdevbox execdevbox exec <name> -- command -v goexec: "command": executable file not found in $PATHcommand -vbash
devbox exec <name> -- bash -lc 'command -v go >/dev/null && go version || echo MISSING_GO'Important For every CLI tool the script uses, check if it exists first and install only if missing. Use platform-appropriate installers and artifacts. For example, on Linux/amd64:
bash
devbox exec <name> -- apt-get install -y --no-install-recommends \
git ca-certificates curl tar build-essential
devbox exec <name> -- curl -fsSL -o /tmp/go.tgz https://go.dev/dl/go<version>.linux-amd64.tar.gz
devbox exec <name> -- tar -xzf /tmp/go.tgz -C /usr/local如果缺少某个工具,只安装工作负载需要的内容。
重要 在安装之前先检查工具是否已存在——在 Linux 上, 自带的工具可能比你预期的更多,包括 Go 等语言。先尝试该命令,再考虑手动安装。
builtin:default使用工具自身的标志来探测,它是一个真实的可执行文件:
bash
devbox exec <name> -- go versioncommand -vdevbox execdevbox exec <name> -- command -v goexec: "command": executable file not found in $PATHcommand -vbash
devbox exec <name> -- bash -lc 'command -v go >/dev/null && go version || echo MISSING_GO'重要 对于脚本使用的每个 CLI 工具,先检查它是否存在,仅在缺失时安装。使用适合平台的安装器和产物。例如,在 Linux/amd64 上:
bash
devbox exec <name> -- apt-get install -y --no-install-recommends \
git ca-certificates curl tar build-essential
devbox exec <name> -- curl -fsSL -o /tmp/go.tgz https://go.dev/dl/go<version>.linux-amd64.tar.gz
devbox exec <name> -- tar -xzf /tmp/go.tgz -C /usr/local3. Run commands with devbox exec
devbox exec3. 用 devbox exec
运行命令
devbox execImportant Run invocations against different devboxes in parallel. Do NOT serialize independent work.
devbox execbash
devbox exec <name> -- <cmd> <args...>devbox ssh <name>devbox execAlternative: native ssh If a workflow uses a tool, which relies on standard SSH tooling (, , etc.), run once to write an entry into your . After that, the devbox is reachable as . Prefer for commands; reach for native ssh when you specifically need standard tooling.
scprsyncdevbox configure-ssh <name>~/.ssh/config<name>.devbox.namespacedevbox execImportant (exec does not give you a shell - but you can ask for one) runs the command directly, so shell operators such as , , redirections and variable expansion are NOT interpreted by default. will not do what you want.
devbox exec&&;devbox exec <name> -- cd /src && makeTwo ways to get multi-step work done, and they trade off differently:
Short multi-step work - invoke a shell explicitly. One round trip, and a mistake costs one re-run:
bash
devbox exec <name> -- bash -lc 'cd /workspaces/<repo-name> && go build ./... && go test ./...'Longer or reusable logic - upload a script. Worth the extra round trips (, , run) when the logic is long, needs careful quoting, or you want the exact steps recorded on the machine. Note that a bug in the script costs a re-upload AND a re-, so prefer while you are still iterating:
uploadchmodchmodbash -lcbash
devbox upload <name> /tmp/script.sh /tmp/script.sh
devbox exec <name> -- chmod +x /tmp/script.sh
devbox exec <name> -- bash /tmp/script.shQuoting is the thing to watch with : wrap the whole program in single quotes and let the remote shell expand , or they will expand locally before the command ever leaves your machine.
bash -lc$VARS重要 针对不同 devbox 的 调用请并行运行。不要将独立的工作串行化。
devbox execbash
devbox exec <name> -- <cmd> <args...>devbox ssh <name>devbox exec备选:原生 ssh 如果某个工作流使用的工具依赖标准 SSH 工具(、 等),运行一次 ,将条目写入你的 。之后,devbox 可以通过 访问。命令优先使用 ;当你确实需要标准工具时,再使用原生 ssh。
scprsyncdevbox configure-ssh <name>~/.ssh/config<name>.devbox.namespacedevbox exec重要(exec 不会给你 shell——但你可以要求一个) 直接运行命令,因此 、、重定向和变量展开等 shell 运算符默认不会被解释。 不会按你的预期工作。
devbox exec&&;devbox exec <name> -- cd /src && make有两种方式完成多步骤工作,它们的取舍不同:
较短的多步骤工作——显式调用 shell。 一次往返,出错只需重跑一次:
bash
devbox exec <name> -- bash -lc 'cd /workspaces/<repo-name> && go build ./... && go test ./...'较长或可复用的逻辑——上传脚本。 当逻辑较长、需要小心引号,或你想在机器上记录确切步骤时,多花几次往返(、、运行)是值得的。注意,脚本中的 bug 会同时导致重新上传和重新 ,所以在迭代期间优先使用 :
uploadchmodchmodbash -lcbash
devbox upload <name> /tmp/script.sh /tmp/script.sh
devbox exec <name> -- chmod +x /tmp/script.sh
devbox exec <name> -- bash /tmp/script.sh使用 时要注意引号:将整个程序用单引号包起来,让远程 shell 展开 ,否则它们在命令离开你的机器之前就会在本地展开。
bash -lc$VARSDetached commands and retained logs
分离命令与保留日志
Use for long-running commands. It starts the command, returns immediately, and prints an exec ID. Use that ID to stream retained and live output with . shows previous executions and their status.
devbox exec -ddevbox logsdevbox logs listbash
devbox exec -d <name> -- <cmd> <args...>对于长时间运行的命令,使用 。它会启动命令、立即返回,并打印一个 exec ID。使用该 ID 通过 流式查看保留的和实时的输出。 显示之前的执行及其状态。
devbox exec -ddevbox logsdevbox logs listbash
devbox exec -d <name> -- <cmd> <args...>exec_<id>
exec_<id>
devbox logs <name> <exec-id>
devbox logs list <name>
**Important** Preflight every required CLI before `set -e` so a missing tool exits with a clear message rather than an opaque failure: `command -v <tool> >/dev/null || { echo "MISSING_TOOL: <tool>"; exit 127; }`. On exit 127 or a `MISSING_TOOL` marker, install the dependency and re-run - do NOT report the run as failed.
**Important** Write all script output to a remote log file and return only a tiny summary by default.
```bash
cat > /tmp/run.sh <<'EOF'
#!/bin/bash
export PATH=/usr/local/go/bin:$PATH
command -v <tool> >/dev/null || { echo "MISSING_TOOL: <tool>"; exit 127; }
set -euo pipefail
mkdir -p /workspaces/tmp
export TMPDIR=/workspaces/tmp
LOG=/workspaces/run.log
cd /workspaces/<repo-name>
status=0
<workload-cmd> >"$LOG" 2>&1 || status=$?
echo "exit=$status log=$LOG bytes=$(wc -c <"$LOG")"
exit "$status"
EOF
devbox upload <name> /tmp/run.sh /tmp/run.sh
devbox exec <name> -- chmod +x /tmp/run.sh
devbox exec <name> -- bash /tmp/run.shdevbox logs <name> <exec-id>
devbox logs list <name>
**重要** 在 `set -e` 之前预检每个所需的 CLI,以便缺失工具以清晰消息退出,而不是不透明的失败:`command -v <tool> >/dev/null || { echo "MISSING_TOOL: <tool>"; exit 127; }`。当退出码为 127 或出现 `MISSING_TOOL` 标记时,安装依赖并重新运行——不要把这次运行报告为失败。
**重要** 默认将所有脚本输出写入远程日志文件,并只返回一个简短的摘要。
```bash
cat > /tmp/run.sh <<'EOF'
#!/bin/bash
export PATH=/usr/local/go/bin:$PATH
command -v <tool> >/dev/null || { echo "MISSING_TOOL: <tool>"; exit 127; }
set -euo pipefail
mkdir -p /workspaces/tmp
export TMPDIR=/workspaces/tmp
LOG=/workspaces/run.log
cd /workspaces/<repo-name>
status=0
<workload-cmd> >"$LOG" 2>&1 || status=$?
echo "exit=$status log=$LOG bytes=$(wc -c <"$LOG")"
exit "$status"
EOF
devbox upload <name> /tmp/run.sh /tmp/run.sh
devbox exec <name> -- chmod +x /tmp/run.sh
devbox exec <name> -- bash /tmp/run.shPull the full log only if the summary shows a non-zero exit.
Pull the full log only if the summary shows a non-zero exit.
devbox download <name> /workspaces/run.log /tmp/run.log
devbox download <name> /workspaces/run.log /tmp/run.log
**Note** Capture the workload's exit code (`status=0; cmd || status=$?`) before printing the summary. Use `devbox download` only for devboxes whose summary reported a non-zero exit, unless specified otherwise.
For test-runner-specific guidance (sharding, parallel runs, the hydrate-and-test recipe, result reporting), see [references/run-tests.md](references/run-tests.md).
**注意** 在打印摘要之前捕获工作负载的退出码(`status=0; cmd || status=$?`)。除非另有说明,只对摘要报告非零退出的 devbox 使用 `devbox download`。
有关测试运行器的具体指导(分片、并行运行、hydrate-and-test 配方、结果报告),请参阅 [references/run-tests.md](references/run-tests.md)。4. Lifecycle
4. 生命周期
bash
devbox create --name <name> [--platform <linux/amd64|macos/arm64>] --image <image> --size <size> [--ephemeral] [--checkout <repo-url>] --purpose "<purpose>"
devbox exec <name> -- <cmd>
devbox exec -d <name> -- <cmd> # run in the background and print an exec ID
devbox logs <name> <exec-id> # stream retained and live output
devbox logs list <name> # inspect retained executions and status
devbox ssh <name> # open an interactive shell; prefer exec for commands
devbox list [-o json] # inspect running devboxes
devbox upload <name> <local-path> <remote-path> # transfer files to devbox
devbox download <name> <remote-path> <local-path> # retrieve files from devbox
devbox configure-ssh <name> # add to ~/.ssh/config for native ssh/scp/rsync
devbox url access <name> [--mode <private|workspace>] -o json # inspect or change devbox.so access
devbox url expose <name> --port <port> [--name <purpose>] -o json # create a persistent devbox.so URL
devbox url get <name> (--port <port> | --name <purpose>) -o json # retrieve an exposed URL
devbox url list <name> -o json # list exposed URLs
devbox url unexpose <name> (--port <port> | --name <purpose>) # remove an exposed URL
devbox port-forward <name> --ports <local:remote,...> # forward devbox ports to localhost (e.g. a dev server or DB)
devbox shutdown <name> # stop a devbox without destroying it
devbox expire <name> --force # tear down a devboxbash
devbox create --name <name> [--platform <linux/amd64|macos/arm64>] --image <image> --size <size> [--ephemeral] [--checkout <repo-url>] --purpose "<purpose>"
devbox exec <name> -- <cmd>
devbox exec -d <name> -- <cmd> # run in the background and print an exec ID
devbox logs <name> <exec-id> # stream retained and live output
devbox logs list <name> # inspect retained executions and status
devbox ssh <name> # open an interactive shell; prefer exec for commands
devbox list [-o json] # inspect running devboxes
devbox upload <name> <local-path> <remote-path> # transfer files to devbox
devbox download <name> <remote-path> <local-path> # retrieve files from devbox
devbox configure-ssh <name> # add to ~/.ssh/config for native ssh/scp/rsync
devbox url access <name> [--mode <private|workspace>] -o json # inspect or change devbox.so access
devbox url expose <name> --port <port> [--name <purpose>] -o json # create a persistent devbox.so URL
devbox url get <name> (--port <port> | --name <purpose>) -o json # retrieve an exposed URL
devbox url list <name> -o json # list exposed URLs
devbox url unexpose <name> (--port <port> | --name <purpose>) # remove an exposed URL
devbox port-forward <name> --ports <local:remote,...> # forward devbox ports to localhost (e.g. a dev server or DB)
devbox shutdown <name> # stop a devbox without destroying it
devbox expire <name> --force # tear down a devboxKeep a devbox alive through long-running work
让 devbox 在长时间运行的工作中保持存活
A devbox with an idle timeout auto-stops when nothing on it looks busy. The Devbox agent treats a
running or SSH command as busy for its whole runtime. Creating or connecting to a
terminal session and receiving HTTP responses through an exposed URL count only as
recent activity for a bounded period. Work not covered by an active exec or SSH command needs an
explicit marker:
devbox execdevbox.sobash
devbox exec <name> -- boxctl task mark <task> # hold the devbox busy
devbox exec <name> -- boxctl task clear-mark <task> # release it
devbox exec <name> -- boxctl task list # what is currently holding itboxctldevbox exec <name> --Mark anything that will run unattended outside an active or SSH command: an
overnight job started in a terminal session, a migration, a queue worker, or a dev server nobody
is hitting yet. A foreground or detached needs no marker while its command is still
running. Without either form of activity the machine can stop mid-task and take the work with it.
devbox execdevbox execImportant Markers have no TTL and nothing cleans them up. One left behind holds the devbox
awake and billed indefinitely, defeating the idle timeout entirely - so always pair a mark with
the matching , on failure paths too. Both commands are idempotent and exit 0 when
the marker already exists or is already gone, which makes them safe in traps and retries. See
references/inside-a-devbox.md for the trap pattern.
clear-markA marker only holds off the idle timeout. and still stop the
machine regardless.
devbox shutdowndevbox expireImportant These commands require devbox CLI v0.0.182 or newer. Check with ; if the installed version is older, run before using them.
devbox urldevbox versiondevbox updateChoose who can open URLs Each devbox has one access mode shared by all of its exposed URLs:
devbox.so- - only the devbox owner.
private - - members of the same Namespace workspace.
workspace
The URL mode initially follows the general devbox access mode, but is configured separately afterward. Changing URL access does not grant or remove SSH, exec, or file access to the devbox.
Inspect or change the Devbox-wide URL mode independently:
bash
devbox url access my-box -o json
devbox url access my-box --mode workspace -o jsonImportant changes this same Devbox-wide setting while exposing a port. It affects every existing and future exposed URL on that devbox; it does not set access only for the new URL. Per-URL access modes are not supported. If URLs need different audiences, ask before changing access or use a separate devbox.
devbox url expose ... --access <mode>Share web work with teammates When the user intends work running in a devbox to be reviewable by teammates, expose its port with and return the resulting URL. The URL remains available after the command exits. Pass when the port's purpose is known so the URL is easier to retrieve and remove later. Prefer JSON output for agent workflows.
--access workspacedevbox.so--nameImportant (how to verify an exposed URL - and how not to) A successful that returns a URL IS your confirmation. Stop there and hand the URL to the user.
devbox url exposeDo NOT try to fetch the URL to "prove" it works. URLs are gated on a signed-in user session, which you do not have and cannot mint - will return , and no API or ID token will change that. That is not a failure and not evidence of anything you need. Chasing a is the single most expensive dead end in this skill: it burns minutes on token endpoints and SSH tunnels to re-confirm a fact the CLI already gave you.
devbox.socurl401 unauthorized401200If you want to confirm the server is actually up before sharing, check it from inside the devbox, where no gateway auth applies:
bash
devbox exec <name> -- curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:<port>/Bind servers to , not , or the proxy cannot reach them.
0.0.0.0127.0.0.1devbox.sobash
devbox url expose my-box --port 3000 --name web --access workspace -o jsonIf the user has not asked to share, omit and preserve the current mode. When sharing intent is unclear, inspect the mode and do not broaden access. If the user explicitly requires every exposed URL on the devbox to be owner-only, set before exposing the new port:
--accessprivatebash
devbox url access my-box --mode private -o json
devbox url expose my-box --port 3000 --name web -o jsonFor local-only access or non-web services, use . Example: maps ports to and . The command blocks the terminal until Ctrl+C, so run it in a dedicated terminal or as a background process.
devbox port-forwarddevbox port-forward my-box --ports 3000:3000,5432:5432localhost:3000localhost:5432Whether and when to call depends on the caller's intent - the test-suite workflow in references/run-tests.md tears down at the end; other use cases may keep the devbox alive.
devbox expireImportant On failure caused by missing dependencies, install them and retry the failing command. Do the same for any uploaded scripts.
带有空闲超时的 devbox 在没有任何忙碌迹象时会自动停止。Devbox agent 会将正在运行的 或 SSH 命令在整个运行期间视为忙碌。创建或连接到终端会话,以及通过暴露的 URL 接收 HTTP 响应,只算作有限时间内的近期活动。不受活动 exec 或 SSH 命令覆盖的工作需要显式标记:
devbox execdevbox.sobash
devbox exec <name> -- boxctl task mark <task> # hold the devbox busy
devbox exec <name> -- boxctl task clear-mark <task> # release it
devbox exec <name> -- boxctl task list # what is currently holding itboxctldevbox exec <name> --请为任何将在活动 或 SSH 命令之外无人值守运行的内容打上标记:在终端会话中启动的过夜任务、迁移、队列 worker,或还没有人访问的 dev 服务器。前台的或分离的 在其命令仍在运行时不需要标记。如果没有这两种活动形式中的任何一种,机器可能会在任务中途停止,并连带丢失工作。
devbox execdevbox exec重要 标记没有 TTL,也没有任何东西会清理它们。遗留的标记会让 devbox 无限期保持唤醒并计费,完全破坏空闲超时——所以始终将标记与对应的 配对,在失败路径上也是如此。这两个命令都是幂等的,当标记已存在或已消失时都会以 0 退出,因此在 trap 和重试中使用是安全的。trap 模式见 references/inside-a-devbox.md。
clear-mark标记只能阻止 空闲 超时。 和 仍然会停止机器,无论是否有标记。
devbox shutdowndevbox expire重要 这些 命令需要 devbox CLI v0.0.182 或更新版本。用 检查;如果安装的版本较旧,请先运行 再使用它们。
devbox urldevbox versiondevbox update选择谁能打开 URL 每个 devbox 有一个所有已暴露 URL 共享的访问模式:
devbox.so- - 仅 devbox 所有者。
private - - 同一 Namespace workspace 的成员。
workspace
URL 模式最初遵循常规的 devbox 访问模式,但之后会单独配置。更改 URL 访问权限并不会授予或撤销对 devbox 的 SSH、exec 或文件访问权限。
独立检查或更改 Devbox 全局的 URL 模式:
bash
devbox url access my-box -o json
devbox url access my-box --mode workspace -o json重要 在暴露端口时, 会更改同一个 Devbox 全局设置。它会影响该 devbox 上所有现有和未来暴露的 URL;它不只是为新 URL 设置访问权限。不支持按 URL 设置访问模式。如果不同 URL 需要面向不同受众,请在更改访问权限前询问,或使用单独的 devbox。
devbox url expose ... --access <mode>与队友共享 Web 工作 当用户希望 devbox 中运行的工作可供队友评审时,使用 暴露其端口,并返回生成的 URL。命令退出后 URL 仍然可用。当端口的用途已知时,传入 ,以便之后更容易检索和移除该 URL。agent 工作流中优先使用 JSON 输出。
--access workspacedevbox.so--name重要(如何验证暴露的 URL——以及如何不验证) 成功的 返回一个 URL,这本身就是确认。到此为止,把 URL 交给用户即可。
devbox url expose不要试图通过抓取 URL 来“证明”它可用。 URL 受已登录用户会话保护,你既没有这种会话也无法铸造一个—— 会返回 ,任何 API 或 ID token 都不会改变这一点。这个 不是失败,也不是你需要处理的证据。追逐 是此 skill 中最昂贵的死胡同:它会浪费几分钟在 token 端点和 SSH 隧道上,只为重新确认 CLI 已经告诉过你的事实。
devbox.socurl401 unauthorized401200如果你想在共享之前确认 服务器 确实已启动,请在 devbox 内部检查,那里不适用网关认证:
bash
devbox exec <name> -- curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:<port>/服务器要绑定到 ,而不是 ,否则 代理无法访问它们。
0.0.0.0127.0.0.1devbox.sobash
devbox url expose my-box --port 3000 --name web --access workspace -o json如果用户没有要求共享,则省略 并保留当前模式。当共享意图不明确时,检查模式且不要扩大访问范围。如果用户明确要求 devbox 上每个暴露的 URL 都仅限所有者,请在暴露新端口前设置 :
--accessprivatebash
devbox url access my-box --mode private -o json
devbox url expose my-box --port 3000 --name web -o json对于仅本地访问或非 Web 服务,使用 。示例: 将端口映射到 和 。该命令会阻塞终端直到按 Ctrl+C,因此在专用终端或后台进程中运行。
devbox port-forwarddevbox port-forward my-box --ports 3000:3000,5432:5432localhost:3000localhost:5432是否以及何时调用 取决于调用者的意图——references/run-tests.md 中的测试套件工作流会在最后销毁 devbox;其他用例可能会让 devbox 保持存活。
devbox expire重要 对于因缺少依赖而导致的失败,请安装依赖并重试失败的命令。对任何上传的脚本也做同样处理。