Modal machine plugin: customizable tools image and resumable sandboxes - #3279
Merged
Conversation
ymichael
force-pushed
the
bb/machine-provider-apis
branch
from
September 9, 2026 03:37
6f566e7 to
a8bf1f6
Compare
ymichael
force-pushed
the
bb/machine-plugin-modal
branch
from
September 9, 2026 05:31
14e1bed to
09f2699
Compare
ymichael
force-pushed
the
bb/machine-plugin-modal
branch
from
September 9, 2026 07:02
1e2e512 to
8c72ff0
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Human comments
What was wrong
Running a project on Modal required configuring a Dockerfile recipe, reviewing/uploading build context, explicitly building an image, and verifying/promoting it before a normal launch. That made cloud machine creation depend on an image-management workflow.
What changed
Adds the optional Modal machine plugin with a simple flow: connect Modal, select a project, and create a machine. A small bundled Dockerfile supplies Debian/Node, Git/GitHub CLI, build/search tools, pnpm, Pi, Codex and Claude Code, running as a non-root user. The first machine launch builds and publishes a Dockerfile-hash-named image; later launches reuse it. The image contains no daemon, project checkout or credentials. Core installs the daemon on demand during bootstrap, enrolls the machine, clones the project and runs its setup hook.
Removes project recipes, context uploads, image verification/promotion, catalog storage/services and their UI/CLI/RPC surfaces. Settings edits the Dockerfile used for future machines, preserving comments and line breaks.
bb modal image set --file PATHsaves a plugin-wide override;image showreads it andimage resetrestores the bundled default. Typed RPCs expose the same operations. Only one FROM followed by RUN, ENV, WORKDIR or USER is accepted; invalid edits preserve the saved version. CLI file reads use the invoking thread host, or primary host without thread context. Saving does not build or change existing machines. Removes the Connection section and its Test connection/Open Machines controls. The Dockerfile is also available throughbb modal image show [--json]and typed plugin RPC; account diagnostics remain available through the CLI and RPC. Retains durable allocation checkpoints, account/app identity pinning, private filesystem snapshots, resume and manual and idle suspension. Automatic retention/keep controls are removed with the base APIs. Existing v3/v4 machine resources normalize on read without needing the removed catalog. Shared standard images remain cached when machines are removed.Adds a direct image-debugging loop:
bb modal image build,bb modal sandbox run,bb modal sandbox exec ID -- COMMAND..., andbb modal sandbox stop ID, with matching typed RPCs. Builds use the same saved Dockerfile/cache and return bounded vendor build logs, including failures. Debug sandboxes skip enrollment, daemon installation and project setup, expire after 30 minutes, and restrict exec/stop to their original account and recorded IDs. Commands preserve argv, output and exit status with a 60-second timeout and bounded output. No interactive terminal API is added.Uses the base machine/enrollment/readiness/lifecycle APIs from #3274, rebased onto
61412bb971, including thereconcileCleanupcallback. No new core database migration or daemon wire changes. Updates the plugin skill, CLI guide, configuration docs and bundled Dockerfile packaging coverage. This PR continues to targetbb/machine-provider-apis.Manual and idle pauses save the filesystem and durably record the snapshot before terminating compute. Resume restores the same BB machine identity. There is no pre-expiry scheduler or deadline timing budget: a sandbox that runs until its configured timeout may lose changes since its last pause. The saved-sandbox identity distinguishes interrupted planned suspension from unexpected compute loss, preventing silent rollback to an older snapshot.
How you verified
Turbo Modal plugin tests: 48 passed; typecheck and lint passed. Covers image reuse, build errors/retries, cancellation before allocation, install-mode bootstrap, account changes, legacy resources and suspend/restore recovery.
Turbo plugin-build artifact tests: 8 passed, including staging the Dockerfile into the distributed plugin.
Built the Dockerfile locally for Linux amd64; ran Node, Git, gh, ripgrep, jq, Python, pnpm, Pi, Codex and Claude Code version checks as the non-root user. Confirmed BB is absent and the user-local installation directory is writable.
Rebuilt and launched
pnpm start:worktreein a persistent BB terminal using isolated development data. Server and daemon health pass; local daemon is connected. Browser-verified the rendered Dockerfile and absence of the removed connection controls; previously checked the machine picker. Verified CLI output exactly matches the shipped Dockerfile without credentials or cloud access. Test app: https://ymichael--24468.getbb.app/settings/plugins/environment-modal-sandboxBefore this rebase, live source CLI against the isolated dev server: Modal account authentication, standard image build, sandbox creation, on-demand daemon installation/enrollment, tool versions, suspend, snapshot restore with a surviving file, and removal passed. E2E exposed and fixed unnecessary provider inputs and missing procps for machine stop. All temporary compute and private snapshots were removed. These live cloud checks have not been repeated after the lifecycle adaptation. Automatic server gh credential forwarding and private repository clone passed. The authorized OpenAI key produced a real Codex response, but shell execution in read-only mode failed with
bwrap: loopback: Failed RTM_NEWADDR: No child process. A normal BB thread is blocked earlier by inherited project-checkout provisioning (Workspace path is already claimed by another launch). Agent E2E is not a pass. The temporary machine and dev API-key setting were removed afterward.After rebase: frozen dependency install, 39 Modal tests/typecheck/lint and runtime builds passed. Persistent dev app restarted with fresh migrated schema; old database preserved. Connect/Modal configuration retained, daemon and HTTP health passed, and browser/CLI Dockerfile checks passed.
After removing pre-expiry scheduling: 39 tests, typecheck and lint passed. Rebuilt/reloaded the running dev plugin; account and HTTP health checks passed and its persisted scheduler registration is absent.
Dockerfile customization: 41 tests/typecheck/lint passed. Live source CLI set/show survived plugin reload with exact text; browser Save/Reset persisted across reload and invalid COPY was rejected without changing the saved definition. Default restored after testing. No cloud build was started for these checks.
Image debugging: 48 tests/typecheck/lint passed. Live source CLI verified cached build, a deliberately failing RUN with diagnostic logs and exit status 19, sandbox tool availability, files persisting across exec calls, command stderr/exit code 7, 128 KiB output truncation, repeated stop, and refusal after stop. Restored the previous Dockerfile and terminated both debug sandboxes.
CI rebase: updated onto base
61412bb971, which fixes the inherited Machines settings heading expectation. All 18 affected settings tests and 48 Modal tests pass locally; typecheck and lint pass.