Execution¶
Core functions for running Claude Code prompts on Fly.io machines.
run
async
¶
Execute a Claude Code prompt on a Fly machine with guaranteed cleanup.
Creates a Fly machine, waits for the Claude Code process to exit, and always destroys the machine afterwards — regardless of success, failure, or cancellation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app_name
|
str
|
The Fly app to run in. |
required |
config
|
MachineConfig
|
Machine configuration including prompt, repos, credentials. |
required |
name
|
str | None
|
Optional human-readable machine name. |
None
|
token
|
str | None
|
Explicit Fly API token. |
None
|
wait_timeout
|
float
|
Max seconds to wait for machine to exit. |
3600.0
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
RunResult
|
class: |
Raises:
| Type | Description |
|---|---|
FlyAPIError
|
If machine creation fails. |
TimeoutError
|
If the machine doesn't exit within wait_timeout. |
Source code in flaude/runner.py
run_and_destroy
async
¶
run_and_destroy(app_name, config, *, name=None, token=None, wait_timeout=3600.0, raise_on_failure=True)
Execute a Claude Code prompt with automatic cleanup, optionally raising on failure.
This is the recommended entry point. It wraps :func:run and optionally
raises :class:MachineExitError when the process exits with a non-zero
code.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app_name
|
str
|
The Fly app to run in. |
required |
config
|
MachineConfig
|
Machine configuration. |
required |
name
|
str | None
|
Optional machine name. |
None
|
token
|
str | None
|
Explicit Fly API token. |
None
|
wait_timeout
|
float
|
Max seconds to wait for exit. |
3600.0
|
raise_on_failure
|
bool
|
If True (default), raise on non-zero exit codes. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
RunResult
|
class: |
Source code in flaude/runner.py
run_with_logs
async
¶
run_with_logs(app_name, config, *, name=None, token=None, wait_timeout=3600.0, item_timeout=None, total_timeout=None, collector=None, server=None, server_port=0, include_stderr=False)
Launch a Claude Code execution and return a streaming log handle.
Sets up log drain infrastructure before creating the machine so
that no early log lines are lost. The returned :class:StreamingRun
yields log lines as they arrive and guarantees machine cleanup.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app_name
|
str
|
The Fly app to run in. |
required |
config
|
MachineConfig
|
Machine configuration (prompt, repos, credentials, …). |
required |
name
|
str | None
|
Optional human-readable machine name. |
None
|
token
|
str | None
|
Explicit Fly API token. |
None
|
wait_timeout
|
float
|
Max seconds to wait for machine to exit. |
3600.0
|
item_timeout
|
float | None
|
Per-line timeout for the log stream ( |
None
|
total_timeout
|
float | None
|
Overall timeout for the log stream ( |
None
|
collector
|
LogCollector | None
|
Existing :class: |
None
|
server
|
LogDrainServer | None
|
Existing :class: |
None
|
server_port
|
int
|
Port for the auto-created server (0 = auto-assign). |
0
|
include_stderr
|
bool
|
Whether the log stream should include stderr lines. |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
StreamingRun
|
class: |
Raises:
| Type | Description |
|---|---|
FlyAPIError
|
If machine creation fails. |
Source code in flaude/lifecycle.py
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 | |
StreamingRun
¶
Handle for a running machine execution with live log streaming.
Acts as an async iterator that yields log lines from the machine's
stdout. After iteration completes (or on early exit), call
:meth:result to get the :class:RunResult with exit details.
Usage::
run = await run_with_logs(app, config)
async for line in run:
print(line)
result = await run.result()
The object can also be used as an async context manager for guaranteed cleanup::
async with await run_with_logs(app, config) as run:
async for line in run:
print(line)
# machine destroyed, server stopped
Source code in flaude/lifecycle.py
result
async
¶
Wait for the machine to exit and return the :class:RunResult.
This also triggers cleanup of the log drain if not already done.
The exit code is determined from the Fly Machines API response.
When the API does not populate the exit code (e.g. because the
machine was force-destroyed or reached failed state without a
clean process exit), the collected log lines are searched for a
[flaude:exit:N] marker written by entrypoint.sh.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
raise_on_failure
|
bool
|
If True (default), raise :class: |
True
|
Raises:
| Type | Description |
|---|---|
MachineExitError
|
If raise_on_failure is True and the run is
considered a failure (non-zero exit or |
Source code in flaude/lifecycle.py
cleanup
async
¶
Stop the log drain server (if owned) and release resources.
Safe to call multiple times — subsequent calls are no-ops.
Source code in flaude/lifecycle.py
RunResult
dataclass
¶
Result of a completed flaude execution.
Attributes:
| Name | Type | Description |
|---|---|---|
machine_id |
str
|
The Fly machine ID that ran the task. |
exit_code |
int | None
|
Process exit code (0 = success). |
state |
str
|
Final machine state (e.g. |
destroyed |
bool
|
Whether the machine was successfully destroyed. |
workspace_files |
tuple[str, ...]
|
Tuple of relative file paths in the workspace. |
wait_for_machine_exit
async
¶
wait_for_machine_exit(app_name, machine_id, *, token=None, poll_interval=_POLL_INTERVAL_SECONDS, timeout=3600.0)
Poll a Fly machine until it reaches a terminal state.
Uses the Fly Machines API GET /machines/{id}/wait endpoint first,
falling back to polling GET /machines/{id} if wait is unavailable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app_name
|
str
|
The Fly app the machine belongs to. |
required |
machine_id
|
str
|
The machine to wait on. |
required |
token
|
str | None
|
Explicit API token. |
None
|
poll_interval
|
float
|
Seconds between poll attempts (fallback only). |
_POLL_INTERVAL_SECONDS
|
timeout
|
float
|
Maximum seconds to wait before giving up. |
3600.0
|
Returns:
| Type | Description |
|---|---|
str
|
A tuple of (final_state, exit_code). exit_code may be None if |
int | None
|
the machine was destroyed before we could read it. |
Raises:
| Type | Description |
|---|---|
TimeoutError
|
If the machine doesn't exit within timeout. |
Source code in flaude/runner.py
run_session_turn
async
¶
run_session_turn(app_name, machine_id, config, *, token=None, wait_timeout=3600.0, raise_on_failure=True)
Execute a single turn of a session on an existing stopped machine.
Updates the machine's config (new prompt, same session ID), starts it,
waits for the Claude Code process to exit, and leaves the machine in
stopped state for the next turn. Does NOT destroy the machine.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app_name
|
str
|
The Fly app the session belongs to. |
required |
machine_id
|
str
|
The stopped machine to resume. |
required |
config
|
MachineConfig
|
Updated config with new |
required |
token
|
str | None
|
Explicit Fly API token. |
None
|
wait_timeout
|
float
|
Max seconds to wait for machine to exit. |
3600.0
|
raise_on_failure
|
bool
|
If True, raise on non-zero exit. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
RunResult
|
class: |
Source code in flaude/runner.py
extract_exit_code_from_logs
¶
Parse the [flaude:exit:N] marker written by entrypoint.sh.
Scans logs in reverse order and returns the first exit code found.
Returns None if no marker is present — e.g. when the container was
killed before the Claude Code process could write it.
This is used as a fallback when the Fly Machines API does not report
an exit code (which can happen if the machine is force-destroyed or
reaches the failed state without a clean exit).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
logs
|
list[str]
|
Log lines collected from the machine's stdout/stderr. |
required |
Returns:
| Type | Description |
|---|---|
int | None
|
The integer exit code extracted from |
int | None
|
|