Bootstrap runner for Flywheel provisioned GPU instances
Project description
Bootstrap
This package hosts the BYOC bootstrapper that:
- Ensures a pinned
codexrelease is available (GitHub release assets). - Fetches the bootstrap payload for a run from the Flywheel backend.
- Launches Codex app-server and streams notifications as logs.
- Collects artifacts (manifest-on-exit) and reports completion or error back to the backend.
Configuration
Bootstrap reads the user's Codex config.toml (Codex schema). See:
- Codex config basics: https://developers.openai.com/codex/config-basic
- Codex config reference: https://developers.openai.com/codex/config-reference
Flywheel adds a small extension under [flywheel] and requires one of:
[flywheel]
# inline instructions (host-specific tips, paths, sandbox notes)
workspace_instructions = """
Use /mnt/work as your workspace. Write artifacts under ./artifacts.
"""
# or: reference a file (relative paths are resolved against the config file directory)
workspace_instructions_file = "workspace_notes.md"
Rules:
- At least one of
workspace_instructionsorworkspace_instructions_fileis required; otherwise bootstrap exits before contacting the server. - If both are set, the file wins and the inline value is ignored (warns once).
- File contents must be non-empty; the path is resolved relative to the config file if not absolute.
Bootstrap also reads a few optional Codex config fields because they affect workspace + sandbox behavior:
cd/workspace_dir(run working directory; defaults to~/.flywheel/runs/<run_id>)sandbox_modeand[sandbox_workspace_write].writable_roots
Prompt assembly (sent as the first Codex turn/start):
- Flywheel engineer context (logging/artifact expectations).
- Task Description (prompt fetched from the server).
- Workspace Instructions (resolved from config as above).
Full example config (recommended starting point):
Update the paths and instructions for your machine.
End-to-end flow (bootstrap.sh → Python bootstrapper)
-
User runs the bootstrapper on their BYOC machine:
BOOTSTRAP_PACKAGE="${FLYWHEEL_BOOTSTRAP_PACKAGE:-flywheel-bootstrap}" uvx --no-cache --from "$BOOTSTRAP_PACKAGE" flywheel-bootstrap \ --run-id <id> --token <token> --config /path/to/config.toml [--server <url>]
Optional: if you have this repo checked out, you can run
project/bootstrap/bootstrap.sh, which installsuvxif missing and then runs the same command. It defaultsFLYWHEEL_BOOTSTRAP_PACKAGEto the localproject/bootstrappath. -
Python entrypoint (
python -m bootstrap):- Parses args/env: requires run id + token, required
--config, optional--server(defaulthttp://localhost:8000). - Loads Codex config.toml, enforces presence of workspace instructions (inline or file), extracts workspace/sandbox settings.
- Parses args/env: requires run id + token, required
-
Workspace resolution:
- Uses
cd/workspace_dirfrom config if set; otherwise~/.flywheel/runs/<run_id>. - Creates the workspace and validates the artifact manifest path is inside sandbox
writable_rootswhen sandboxing is enabled; else exits with an error.
- Uses
-
Engineer runtime availability:
- If
BOOTSTRAP_MOCK_ENGINEERis set, skips agent launch and runs a mock flow (used in tests). - Else, download a pinned Codex release asset and mark it executable.
- If
-
Fetch bootstrap payload:
GET <server>/runs/<run_id>/bootstrapwithX-Run-Token; payload contains the task prompt.
-
Build prompt text:
- Combine base Flywheel engineer context, “Task Description” (server prompt), and “Workspace Instructions” (user config) into one prompt string.
-
Launch engineer via Codex app-server:
- Create a per-run
CODEX_HOMEdirectory at<workspace>/.codex_homecontaining a copiedconfig.toml(with~/expanded). - Best-effort copy auth credentials from
~/.codex/auth.jsoninto<workspace>/.codex_home/auth.jsonso Codex can authenticate. - Launch
codex app-serveras a subprocess and speak JSON-RPC over stdio (newline-delimited JSON;"jsonrpc":"2.0"header omitted):initialize+initializedthread/startturn/start(first prompt = full Flywheel prompt; subsequent prompts = autonomous resume)turn/interruptfor takeover/resume- Stream
turn/*,item/*, and delta notifications (item/agentMessage/delta,item/commandExecution/outputDelta, etc.)
- Bootstrap auto-accepts command/file approvals (for-session) when Codex requests them.
- Start a heartbeat thread posting
/runs/{id}/heartbeat. - Start a run-control polling thread (
/runs/{id}/control/poll) to handle:take_over(interrupt autonomous prompt turn; enter interactive mode)send_input(start a new Codex turn with user input in interactive mode)resume_autonomous(return to autonomous mode)
- Convert
thread/tokenUsage/updatedtotals into aturn.completedusage log for billing. - Stream app-server notifications as logs to
/runs/{id}/logs.
- Create a per-run
-
After the engineer prompt turn ends:
- If code persistence is enabled, bootstrap commits/pushes non-artifact changes:
- Excludes manifest-declared artifact paths from the git commit
- Skips oversized files (default cap: 95 MiB, configurable via
FLYWHEEL_GIT_MAX_COMMIT_FILE_SIZE_BYTES)
- Artifact files referenced by
payload.path/payload.fileare embedded into artifact payloads when they are below the transfer threshold (default: 16 MiB, configurable viaFLYWHEEL_ARTIFACT_BLOB_THRESHOLD_BYTES). - Read
flywheel_artifacts.json; if missing/malformed/empty, retry up toMAX_ARTIFACT_RETRIESby prompting the engineer to fix/write the manifest. - POST artifacts to
/runs/{id}/artifacts; POST/completeon exit 0, else/errorwith the exit code. - Stop/join the heartbeat thread.
- If code persistence is enabled, bootstrap commits/pushes non-artifact changes:
-
Mock mode (
BOOTSTRAP_MOCK_ENGINEER=1):- Sends a heartbeat, a few logs, writes a mock artifact manifest, returns 0 (used in e2e tests).
Next steps
- Iterate on prompts / general polish.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flywheel_bootstrap_staging-0.1.9.202602111602.tar.gz.
File metadata
- Download URL: flywheel_bootstrap_staging-0.1.9.202602111602.tar.gz
- Upload date:
- Size: 70.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a87805185a3f01fd84a668d67a3052241bf1058cfc877def7118edcc87f7ddf
|
|
| MD5 |
0893aaf071964001ed013b9e7fea55c3
|
|
| BLAKE2b-256 |
88b33e5a4f8fd5d92ce5555f7e39465ddb86c608c137483aa894fb6776407a25
|
File details
Details for the file flywheel_bootstrap_staging-0.1.9.202602111602-py3-none-any.whl.
File metadata
- Download URL: flywheel_bootstrap_staging-0.1.9.202602111602-py3-none-any.whl
- Upload date:
- Size: 41.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
745fcb84d36014a58159e43f6acfac5040c605a564ac447f6d9b1226557dfb53
|
|
| MD5 |
298b934670c45f83de66ce0f3de2a183
|
|
| BLAKE2b-256 |
a4d87907294916ce7499dd9c440dea905675bda0c72ca2f9cec0ce785f8b66d1
|