fabro/docs/human-tools/vs-code.mdx
brynary-fabro[bot] ac355d58c7
Extract fabro resume subcommand (#137)
This PR extracts the `fabro resume` subcommand from `fabro run`,
replacing the `--resume` and `--run-branch` flags with a dedicated, more
ergonomic interface. Users can now run `fabro resume <RUN_ID>` instead
of constructing `fabro run --run-branch fabro/run/<RUN_ID>` manually,
and the command also accepts run ID prefixes (matching the pattern
established by `fabro rewind` and `fabro fork`). Checkpoint-file-based
resumption is also supported via `fabro resume --checkpoint
path/to/checkpoint.json --workflow workflow.fabro`.

The implementation moves the ~315-line `run_from_branch()` function out
of `run.rs` and into a new `commands/resume.rs` module, splitting it
into two preparation paths (`prepare_from_checkpoint` and
`prepare_from_branch`) that converge on a shared `run_resumed()` tail.
Several previously private helpers in `run.rs` are widened to
`pub(crate)` to allow sharing: `local_sandbox_with_callback`,
`resolve_ssh_config`, `resolve_ssh_clone_params`,
`resolve_preserve_sandbox`, `generate_retro`, `write_finalize_commit`,
`print_final_output`, `print_assets`, and the new `default_run_dir`
helper extracted from duplicated inline logic. The `RunArgs` struct
loses its `resume` and `run_branch` fields along with their
`conflicts_with` annotations, and `RunSpec` drops the corresponding
fields with `#[serde(default)]` for backward compatibility.

Documentation across `docs/reference/cli.mdx`,
`docs/execution/checkpoints.mdx`, and
`docs/core-concepts/how-fabro-works.mdx` is updated to reflect the new
interface, and the `rewind`/`fork` commands now hint `fabro resume
<short-prefix>` instead of the full branch name.

### Fabro Details

<details>
<summary>Ran 9 stages in 30m 25s for $6.70</summary>

| Stage | Duration | Cost | Retries |
|---|---|---|---|
| start | 0s | – | 0 |
| toolchain | 0s | – | 0 |
| preflight_compile | 1m 10s | – | 0 |
| preflight_lint | 13s | – | 0 |
| implement | 18m 30s | $3.95 | 0 |
| simplify_opus | 9m 38s | $2.75 | 0 |
| simplify_gpt | 0s | – | 0 |
| verify | 19s | – | 0 |
| fmt | 1s | – | 0 |
| **Total** | **30m 25s** | **$6.70** | **0** |

</details>

<details>
<summary>Ran <code>ImplementPlan.fabro</code> (12 nodes and 15
edges)</summary>

```dot
digraph ImplementPlan {
    graph [
        goal="Implement and simplify",
        model_stylesheet="
            * { model: claude-opus-4-6; }
        "
    ]
    rankdir=LR

    start [shape=Mdiamond, label="Start"]
    exit  [shape=Msquare, label="Exit"]

    toolchain         [label="Toolchain", shape=parallelogram, script="command -v cargo >/dev/null || { curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && sudo ln -sf $HOME/.cargo/bin/* /usr/local/bin/; }; cargo --version 2>&1", max_retries=0]
    preflight_compile [label="Preflight Compile", shape=parallelogram, script="cargo check -q --workspace 2>&1", max_retries=0]
    preflight_lint    [label="Preflight Lint", shape=parallelogram, script="cargo clippy -q --workspace -- -D warnings 2>&1", max_retries=0]
    fix_lints         [label="Fix Lints", prompt="The preflight lint step failed. Read the build output from context and fix all clippy lint warnings.", max_visits=3]
    implement         [label="Implement", prompt="Read the plan file referenced in the goal and implement every step. Make all the code changes described in the plan. Use red/green TDD."]
    simplify_opus     [label="Simplify (Opus)", prompt="@prompts/simplify.md"]
    simplify_gpt      [label="Simplify (GPT-54)", prompt="@prompts/simplify.md", model="gpt-54"]
    verify            [label="Verify", shape=parallelogram, script="cargo clippy -q --workspace -- -D warnings 2>&1 && cargo nextest run --cargo-quiet --workspace --status-level fail 2>&1", goal_gate=true, retry_target="fixup"]
    fixup             [label="Fixup", prompt="The verify step failed. Read the build output from context and fix all clippy lint warnings and test failures.", max_visits=3]
    fmt               [label="Format", shape=parallelogram, script="cargo fmt --all 2>&1", max_retries=0]

    start -> toolchain
    toolchain -> preflight_compile [condition="outcome=success"]
    toolchain -> exit
    preflight_compile -> preflight_lint [condition="outcome=success"]
    preflight_compile -> exit
    preflight_lint -> implement [condition="outcome=success"]
    preflight_lint -> fix_lints
    fix_lints -> preflight_lint
    implement -> simplify_opus -> simplify_gpt -> verify
    verify -> fmt   [condition="outcome=success"]
    verify -> fixup
    fixup -> verify
    fmt -> exit
}

```

</details>

⚒️ Generated with [Fabro](https://fabro.sh)

---------

Co-authored-by: Fabro <noreply@fabro.sh>
Co-authored-by: Bryan Helmkamp <bryan@brynary.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:45:06 -04:00

53 lines
2.8 KiB
Text

---
title: "VS Code"
description: "Open sandbox environments in VS Code for interactive editing and debugging"
---
When a Daytona sandbox has [SSH access](/human-tools/ssh-access) enabled, you can connect VS Code directly to the sandbox using the built-in [Remote - SSH](https://code.visualstudio.com/docs/remote/ssh) extension. This gives you a full IDE experience — editing, terminal, debugging, port forwarding — inside the same environment where your workflow agents are running.
<Note>
VS Code remote access requires [SSH access](/human-tools/ssh-access), which is only available with the Daytona sandbox provider.
</Note>
## Prerequisites
- [VS Code](https://code.visualstudio.com/) with the [Remote - SSH](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh) extension installed
- A running Daytona sandbox with SSH access enabled
## Connecting to a sandbox
1. Start a workflow with a preserved Daytona sandbox:
```bash
fabro run workflow.fabro --sandbox daytona --preserve-sandbox
```
2. Use `fabro ssh` to get the connection command:
```bash
fabro ssh <run-id> --print
```
3. In VS Code, open the Command Palette (`Cmd+Shift+P` / `Ctrl+Shift+P`) and run **Remote-SSH: Connect to Host...**
4. Paste the hostname from the SSH command (e.g. `daytona@fabro-20260307-143022-a3f2.ssh.daytona.io`)
5. Once connected, open the workspace folder at `/home/daytona/workspace`
VS Code installs its server component on the sandbox automatically. After the initial setup, you have full IDE access to the remote environment.
## What you can do
Once connected, VS Code operates as if the sandbox filesystem were local:
- **Edit files** — Full IntelliSense, code navigation, and refactoring on the sandbox filesystem
- **Terminal** — Open integrated terminals that run directly on the sandbox
- **Debug** — Attach debuggers to processes running in the sandbox using standard launch configurations
- **Port forwarding** — Access web servers and other services running in the sandbox from your local browser
- **Extensions** — VS Code extensions install on the sandbox automatically, so linters, formatters, and language servers work as expected
## Tips
- **Use `--preserve-sandbox`** — Without it, the sandbox is destroyed when the workflow finishes and your VS Code session disconnects. Combine with `auto_stop_interval` in your [run config](/execution/run-configuration) to control idle timeout.
- **Pair with human gates** — When a workflow pauses at a [human gate](/workflows/human-in-the-loop), connect via VS Code to review the agent's changes before approving.
- **SSH credential lifetime** — Daytona SSH credentials expire after 60 minutes by default. If your VS Code session disconnects, run `fabro ssh <run-id>` again to get fresh credentials (use `--ttl` to set a custom expiry).