A

Autonomous Agents Agentic Workflow

Open App Editing Session — Autonomous Agents Agentic Workflow

Boot a project's dev server on this VM, verify it serves, submit the ready report, then ride the live session

Available free v1.24.0 Browser
$ sidebutton install agents
Download ZIP
se

Opens a live editing session on a workspace project. The agent syncs the project, starts its own dev server on the VM, verifies the server actually answers, and submits the ready report. That report IS the readiness signal: the boot turn completing is what tells the portal the session is connected (SCRUM-1965), so the boot turn carries no screenshot step and depends on no chrome binary. That first turn is the whole job — it completes as soon as the ready report is posted, and the user's chat then continues on the same still-alive Claude session, one turn per message.

The dev server is the live lane. It is started detached and bound to the loopback interface, so it survives the end of every turn and is reachable only through the agent daemon's authenticated preview passthrough (SP-B/SP-C) — never as an open port on the VM. Reconnecting onto the same workspace reuses a server that is still healthy instead of booting a second one, so a session can be resumed without tripping over its own port.

Durability is git, uniformly for every repo: each turn ends with a real commit pushed to the project's branch, so a reclaimed spot VM costs at most the current turn. A rejected push is rebased once and retried once; if it still will not land, the reply says so and the commit rides into the next turn rather than being forced over someone else's work. That is also why the session rules below insist the working tree stays publishable at all times — nothing secret may ever be written into the project, and evidence files belong in the artifacts directory outside it.

Steps

  1. 1.
    Open a terminal
    title
    Agent: App Editing Session
    cwd
    {{app_path}}
    terminal.open
  2. 2.
    Run a terminal command
    cmd
    |
    terminal.run

Workflow definition

schema_version: 1
# Id is a CONTRACT, deliberately without the `agent_` prefix: executePipeline writes this exact
# string into ~/.sidebutton/job-context.json (.workflow_id) on the VM, the portal floor entry keys
# on it, and SP-D's per-turn Stop-hook branch (SCRUM-1937) will read it from there. Renaming it
# later is a fleet-wide coordination job — treat it as frozen.
id: app_edit_session
title: "Open App Editing Session"
description: "Boot a project's dev server on this VM, verify it serves, submit the ready report, then ride the live session"
overview: |
  Opens a live editing session on a workspace project. The agent syncs the project, starts its own dev server on the VM, verifies the server actually answers, and submits the ready report. That report IS the readiness signal: the boot turn completing is what tells the portal the session is connected (SCRUM-1965), so the boot turn carries no screenshot step and depends on no chrome binary. That first turn is the whole job — it completes as soon as the ready report is posted, and the user's chat then continues on the same still-alive Claude session, one turn per message.

  The dev server is the live lane. It is started detached and bound to the loopback interface, so it survives the end of every turn and is reachable only through the agent daemon's authenticated preview passthrough (SP-B/SP-C) — never as an open port on the VM. Reconnecting onto the same workspace reuses a server that is still healthy instead of booting a second one, so a session can be resumed without tripping over its own port.

  Durability is git, uniformly for every repo: each turn ends with a real commit pushed to the project's branch, so a reclaimed spot VM costs at most the current turn. A rejected push is rebased once and retried once; if it still will not land, the reply says so and the commit rides into the next turn rather than being forced over someone else's work. That is also why the session rules below insist the working tree stays publishable at all times — nothing secret may ever be written into the project, and evidence files belong in the artifacts directory outside it.

category:
  level: pipeline
  domain: engineering

metadata:
  agent: true
  role: se
  # Gate-verdict vocabulary (PLAYBOOKS.md §5). Both tokens are boot-turn outcomes: the boot report
  # ends with SESSION_READY once the dev server serves, or BOOT_FAILED when it never does. Later
  # chat turns emit neither — they are conversation, not a gated step result.
  verdicts: [SESSION_READY, BOOT_FAILED]

params:
  agentic_app:
    type: string
    default: "cc"
    description: "Agent-app slug selecting the per-run env file ~/.agent-env.d/<slug> (AAP-C); 'cc'/subscription clears provider vars"
  entry_path:
    type: string
    default: "~/workspace"
    description: "Workspace directory the dispatch targets; force-injected by executePipeline and used as the workspace_slug match"
  # --- App contract (SCRUM-1964 / SP2-B) ---
  # Resolved per project from workspace_projects and passed through by the portal's dispatch, so a
  # session no longer guesses which directory of a monorepo is the app or how to start it. Every one
  # defaults to "" — a project that declares no contract boots exactly as it did before these existed.
  # NOTE: an absent param resolves to "" on the VM, NOT to the default below, so any value used as a
  # path must be joined portal-side (that is what app_path is) rather than templated from two params.
  project_path:
    type: string
    default: "~/workspace"
    description: "The project checkout — the git root the session commits and pushes from"
  app_dir:
    type: string
    default: ""
    description: "Directory INSIDE the checkout that holds the app; empty means the checkout root"
  app_path:
    type: string
    default: "~/workspace"
    description: "project_path joined with app_dir — the directory the session's terminal opens in"
  dev_cmd:
    type: string
    default: ""
    description: "Command that starts the dev server, run from app_path; empty means read package.json and pick the dev script"
  dev_port:
    type: string
    default: ""
    description: "Port the dev server must listen on; empty uses the project's framework convention (Astro 4321, Vite 5173, Next 3000)"
  dev_env:
    type: string
    default: ""
    description: "Space-separated non-secret KEY=VALUE flags to export before the dev command, e.g. SB_DEV_SESSION=1"
  preview_path:
    type: string
    default: ""
    description: "Route the preview should open on when / is not the app's entry, e.g. /portal"
  hint:
    type: string
    default: ""
    description: "Optional extra instructions for the agent"

steps:
  - type: terminal.open
    title: "Agent: App Editing Session"
    # The APP directory, not the workspace root (SCRUM-1964). Portal-joined into one param on
    # purpose: "{{project_path}}/{{app_dir}}" would resolve to a bare "/" on any run that carries
    # no project, and terminal.open would open the session at the filesystem root.
    cwd: "{{app_path}}"
  - type: terminal.run
    cmd: |
      source ~/.agent-env
      # AAP-C (SCRUM-1506) + AAP-17 (SCRUM-1653): clear EVERY provider var an agent-app can deliver so
      # none hijacks/poisons a subscription run. A stray global ANTHROPIC_MODEL / ANTHROPIC_SMALL_FAST_MODEL
      # needs no CLAUDE_CODE_USE_* flag, so the old ${!CLAUDE_CODE_USE_@} glob never caught it — it survived
      # into the run and 404-ed aux/small-fast calls against api.anthropic.com. This explicit list mirrors
      # AGENT_APP_ENV_KEYS 1:1 (the-assistant website/src/lib/cloud/agent-app-env.ts — the single source of
      # truth; a parity test in each repo guards the two from drifting). Explicit over a glob: the union has
      # non-ANTHROPIC_ members (AWS_REGION, AWS_PROFILE, CLOUD_ML_REGION, CLAUDE_CODE_MAX_OUTPUT_TOKENS) and
      # a ${!AWS_@} glob would over-clear unrelated creds. Then source the per-run app env by slug when it
      # exists; no file => subscription/default. base/19-secrets stages ~/.agent-env.d/<slug>.
      unset \
        ANTHROPIC_API_KEY ANTHROPIC_BASE_URL ANTHROPIC_AUTH_TOKEN CCR_CONFIG_B64 \
        CLAUDE_CODE_USE_BEDROCK AWS_REGION AWS_PROFILE ANTHROPIC_MODEL \
        ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION ANTHROPIC_SMALL_FAST_MODEL CLAUDE_CODE_MAX_OUTPUT_TOKENS \
        CLAUDE_CODE_USE_VERTEX CLOUD_ML_REGION ANTHROPIC_VERTEX_PROJECT_ID ANTHROPIC_VERTEX_BASE_URL \
        CLAUDE_CODE_USE_FOUNDRY ANTHROPIC_FOUNDRY_RESOURCE ANTHROPIC_FOUNDRY_BASE_URL \
        ANTHROPIC_DEFAULT_OPUS_MODEL ANTHROPIC_DEFAULT_SONNET_MODEL ANTHROPIC_DEFAULT_HAIKU_MODEL
      if [ -f "$HOME/.agent-env.d/{{agentic_app}}" ]; then
        source "$HOME/.agent-env.d/{{agentic_app}}"
      fi
      claude --dangerously-skip-permissions "$(cat <<'SB_PROMPT'
      you are opening a LIVE EDITING SESSION on the app in the current directory ({{app_path}}). the project checkout — the git root you commit and push from — is {{project_path}}, and the app itself lives in {{app_dir}} inside it (empty means the app IS the checkout root). load the dev-session knowledge module (skill://agents/dev-session/_skill.md) before you touch anything — it carries the port conventions, the HMR-behind-two-proxies config, and the autosave rules this session runs on.
      BOOT — this turn does the boot and nothing else. do every step in the FOREGROUND, then end the turn.
      1. SYNC: git commands belong at the checkout root, so `cd {{project_path}}` for this step and come back to {{app_path}} after. if that is not a git repo either, the dispatch handed you a workspace root — `cd` into the project checkout inside it (the single repo directory, or the one the hint names) and say which you picked. then `git fetch` and `git pull --ff-only`. NEVER `git reset --hard`, `git checkout -- .` or `git clean` — on a reconnect the local branch carries autosave commits that exist nowhere else, and destroying them destroys the user's work. if the pull cannot fast-forward, keep the local tree, say so, and continue.
      2. INSTALL: install dependencies only when they are missing or the lockfile moved since the last install (node_modules absent, or the lockfile is newer). an already-installed tree is a no-op — do not reinstall for its own sake.
      3. START THE DEV SERVER: the project may declare a contract — USE IT WHEN IT IS SET, it is the operator telling you what this repo actually needs, and only fall back to guessing when a field is empty. the dev command is `{{dev_cmd}}` when that is non-empty, otherwise read package.json and pick the dev script. export `{{dev_env}}` first when that is non-empty (space-separated KEY=VALUE flags — `export {{dev_env}}` works as written, and they are non-secret by construction). the port is {{dev_port}} when that is set, otherwise the project's framework convention (Astro 4321, Vite 5173, Next 3000). FIRST check whether a healthy server already answers on that port: on a reconnect it usually does, and you must REUSE it rather than boot a second one (a double boot either dies on EADDRINUSE or silently lands on another port the preview cannot reach). otherwise start it DETACHED so it outlives this turn and the 60-minute session tidy — `setsid nohup <dev command> >"$HOME/dev-server.log" 2>&1 &`. PASS THE IPv4 HOST FLAG EXPLICITLY: `--host 127.0.0.1` for Astro and Vite, `-H 127.0.0.1` for Next. left to itself Astro/Vite binds the IPv6 loopback `[::1]` ONLY, and the preview passthrough dials `127.0.0.1` — the server looks perfectly healthy in its log and is unreachable. never bind 0.0.0.0 either: the VM opens no new ports, the preview arrives through the agent daemon's authenticated passthrough.
      4. VERIFY IT SERVES: poll `curl -sS -o /dev/null -w '%{http_code}' http://127.0.0.1:<port>/` until curl reports ANY http status (curl prints 000 while nothing is listening), for at most ~90 seconds. any status proves the server is up — a project with no route at `/` legitimately answers 404 while being perfectly healthy, so do NOT require 200 on `/`. do not declare readiness off a PID or a log line either. if nothing ever answers, report the failure with the last ~40 lines of ~/dev-server.log and finish the turn with BOOT_FAILED as the final line.
      5. RESOLVE THE ENTRY ROUTE: pick the route the preview should open on — `{{preview_path}}` when that is non-empty, otherwise `/`, or the actual first page when `/` 404s (check src/pages or the router). it must be a route you have seen answer, so `curl` it the same way as step 4 before you name it. no screenshot: this turn takes no picture and needs no chrome binary — the report you post next IS the readiness signal the portal keys on.
      6. REPORT AND STOP: finish immediately with the boot report, in this order and nothing more: (a) one status line — project and branch, the dev command, the PORT, the ENTRY ROUTE from step 5, and the local URL; (b) a SHORT kickoff analysis the user reads first — what this project already is (stack, entry route, the handful of things that exist), then the next steps worth taking ordered by value, closing with one question back to them; (c) a final block of 3-4 suggestion chips, each a short imperative the user could send back as-is (≤60 chars), formatted exactly as a `SUGGESTIONS:` line followed by one `- chip text` per line — the portal renders these as one-click chips, so nothing may follow the block except the verdict line; (d) the final line exactly SESSION_READY. keep (b) tight — a few sentences, no headings, no file dumps. this turn's end COMPLETES the job, and that completion is exactly what flips the window to connected; so do not hold the turn open, do not tail the log, and never wait on the dev server.
      SESSION RULES — every later turn. each user message is one turn: do what it asks, then end the turn promptly so the reply reaches the user.
      - TURN END = COMMIT + PUSH, uniformly, in every repo. commit with a real message describing the change (never "wip"/"autosave"), then `git push` the branch you are on — for a project session that is main. a commit you did not push exists only on a VM that can be reclaimed. include any commit an earlier turn had to leave local. treat every turn end as a publish: leave the tree building and coherent.
      - IF THE PUSH IS REJECTED (someone else advanced the branch): `git pull --rebase` ONCE and push ONCE more. if it is still rejected, STOP retrying — say so plainly in your reply, keep the commit local, and push it again at the end of the next turn. never `git push --force`, never reset to origin: a rejected push means someone else's work is on that branch.
      - never destroy your own autosave commits — no `git reset --hard`, no force-push over the session branch. if you must undo, revert forward with a new commit.
      - NEVER PARK CREDENTIALS: nothing secret goes into the project worktree — no .env with real values, no tokens in config or committed fixtures. the only credential this VM holds is the sb_token already in ~/.agent-env, and every turn publishes the tree.
      - keep evidence (screenshots, reports, datasets) in ~/workspace/artifacts/ — the directory the artifacts lane actually uploads from — never inside the project.
      - the dev server stays UP across turns: never stop or restart it at the end of a turn. if a change needs a restart, or the server died, restart it exactly as in steps 3-4 and say so in your reply.
      - report honestly: if a change did not work, say what you saw. the user is watching the live preview and will see it too.
      {{hint}}
      SB_PROMPT
      )"