Skip to content

docs(cloud-agents): document customizing workspace snapshots#105

Merged
hongyi-chen merged 9 commits into
mainfrom
oz/docs/snapshot-declarations
May 20, 2026
Merged

docs(cloud-agents): document customizing workspace snapshots#105
hongyi-chen merged 9 commits into
mainfrom
oz/docs/snapshot-declarations

Conversation

@hongyi-chen
Copy link
Copy Markdown
Collaborator

Summary

Adds a new page documenting how to customize end-of-run workspace snapshots for cloud agent handoff, and wires it into the Handoff sidebar group plus cross-links from existing pages.

The end-of-run snapshot pipeline backs both local-to-cloud and cloud-to-cloud handoff. Today the bundled warp-agent-docker image ships a declarations script that snapshots every git repo under the agent's workspace, but customers running outside that image (custom Docker bases, self-hosted Direct backend, unmanaged oz agent run in CI) get no snapshotting by default and have no docs explaining how to opt back in. This PR closes that gap so we can:

  • Downgrade the missing-script ERROR log in the driver to INFO without orphaning users
  • Surface a CLI/log pointer to a real docs URL when snapshotting is a no-op

What this PR adds

  • New page: src/content/docs/agent-platform/cloud-agents/handoff/snapshots.mdx
    • When to customize snapshots
    • How snapshotting works (script invocation, per-run output file)
    • The two env vars Warp respects: OZ_SNAPSHOT_DECLARATIONS_SCRIPT and OZ_SNAPSHOT_DECLARATIONS_FILE
    • JSONL declarations file format (v1 schema, repo vs file, absolute paths)
    • Minimal bash script template, referencing the canonical implementation
    • "Static declarations file (no script)" pattern for fixed-workspace runs
    • --no-snapshot for disabling per run
  • Sidebar wire-up under Handoff in src/sidebar.ts
  • Single-sentence cross-links from handoff/local-to-cloud, handoff/cloud-to-cloud, self-hosting/unmanaged, and self-hosting/index

Validation

  • python3 .agents/skills/check_for_broken_links/check_links.py --internal-only — 0 broken internal links across 329 files.
  • python3 .agents/skills/style_lint/style_lint.py --changed — Only flagged 2 pre-existing false positives in unmanaged.mdx's description, where "the oz agent run CLI" is matched as the deprecated "Oz agent" phrasing. Not introduced by this PR and out of scope to fix.

Out of scope

  • Updating the CLI/log output to reference the new URL (lands separately in warp-internal).
  • Documenting bundled-script-internal env vars like OZ_SNAPSHOT_SCAN_ROOTS and OZ_SNAPSHOT_JQ — these are conventions of the bundled script, not part of Warp's contract.

Conversation: https://staging.warp.dev/conversation/b33e43a6-1d68-48b4-a3bb-7721c4e87122
Run: https://oz.staging.warp.dev/runs/019e4216-6f14-7ac4-9d4e-5186b5227a2a
Plans:

This PR was generated with Oz.

Add a new page under cloud-agents/handoff documenting how to customize
the end-of-run snapshot pipeline that backs local-to-cloud and
cloud-to-cloud handoff. Targets self-hosted and CLI users who run
outside the bundled warp-agent-docker image and need to provide their
own declarations script (or a static declarations file) for handoff
to work.

The page covers:
- When to customize (custom Docker image, Direct backend, unmanaged
  oz agent run in CI)
- The two env vars Warp respects (OZ_SNAPSHOT_DECLARATIONS_SCRIPT,
  OZ_SNAPSHOT_DECLARATIONS_FILE)
- The JSONL declarations file format (v1 schema, repo vs file kinds)
- A minimal bash script template + the static declarations file
  pattern (no script needed)
- --no-snapshot for disabling snapshots per run

Wire the new page into the Handoff sidebar group and add
single-sentence cross-links from local-to-cloud, cloud-to-cloud,
self-hosting/unmanaged, and self-hosting/index so readers arriving
from any of those entry points can find it.

Co-Authored-By: Oz <oz-agent@warp.dev>
@cla-bot cla-bot Bot added the cla-signed label May 19, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented May 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment May 19, 2026 11:52pm

Request Review

- Drop the "Continue locally" mention from the intro. Cloud-to-local
  handoff doesn't apply workspace patches to a local checkout (per
  handoff/index.mdx), so the claim was misleading.
- Replace "empty workspace" with "without the prior session's
  uncommitted changes". The cloud workspace isn't empty without a
  snapshot — the environment still clones repos at HEAD; what's
  missing is the uncommitted delta.
- Restructure "How snapshotting works" to lead with the two modes
  (script-driven vs static) before walking through each one. Removes
  the implicit assumption that the script always runs.
- Drop the setup_command half of the Direct backend tip. setup_command
  injects env vars via OZ_ENVIRONMENT_FILE, which is more indirection
  than this page should explain — just point at `environment` config.
- Remove the local-to-cloud cross-link to the snapshots page. The
  local-to-cloud path uses upload_snapshot_for_handoff() with Vec
  arguments, not OZ_SNAPSHOT_DECLARATIONS_SCRIPT, so the cross-link
  could mislead readers. cloud-to-cloud, self-hosting/unmanaged, and
  self-hosting/index still link to the page.

Co-Authored-By: Oz <oz-agent@warp.dev>
@hongyi-chen hongyi-chen requested a review from harryalbert May 19, 2026 21:57
@hongyi-chen hongyi-chen marked this pull request as ready for review May 19, 2026 21:57
@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 19, 2026

@hongyi-chen

I'm starting a first review of this pull request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR adds a new Cloud Agents handoff page that explains workspace snapshot customization, wires it into the sidebar, and adds cross-links from related handoff and self-hosting docs. The structure and most technical details align with the available implementation context.

Concerns

  • The new page should warn users that declared file paths are uploaded as snapshot content, especially because the examples mention logs and scratch files.
  • The bash template should escape JSON metacharacters in repository paths before writing declarations.
  • The related-page link claims the CLI reference includes --no-snapshot, but that flag is not documented there.

Security

  • Add an explicit privacy/data-handling caution for arbitrary file declarations so users do not accidentally snapshot secrets, credentials, or sensitive logs.

Verdict

Found: 0 critical, 0 important, 3 suggestions

Approve with nits

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

* **Paths must be absolute.** Relative paths are rejected and logged as malformed.
* **Prefer `repo` over `file` for paths inside a repository.** Warp generates a git diff for each `repo` entry (tracked changes plus untracked files), so individual `file` entries inside that repo are redundant and dropped before upload. Including a `repo` entry is also more extensible than enumerating files.
* **Repos are diffed, not copied wholesale.** Only changed files are uploaded for each `repo` entry, so listing a large repository is cheap when the agent's changes are small.
* **`file` entries are for paths outside any declared repo** — for example, logs the agent wrote to `/tmp` or scratch files in `$HOME`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 [SUGGESTION] [SECURITY] This section encourages declaring arbitrary files such as logs or scratch files, but it never warns that declared paths are uploaded to Warp. Add a caution to exclude secrets, credential stores, and sensitive logs before users copy this pattern.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems like a good call maybe

Comment on lines +97 to +98
printf '{"version":1,"kind":"repo","path":"%s"}\n' "$repo_root" \
>> "$OZ_SNAPSHOT_DECLARATIONS_FILE"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 [SUGGESTION] The script writes repo_root directly into JSON, so paths containing quotes or backslashes produce malformed declarations that Warp skips. Escape JSON metacharacters before writing the line.

Suggested change
printf '{"version":1,"kind":"repo","path":"%s"}\n' "$repo_root" \
>> "$OZ_SNAPSHOT_DECLARATIONS_FILE"
repo_json="$(printf '%s' "$repo_root" | sed 's/\\/\\\\/g; s/"/\\"/g')"
printf '{"version":1,"kind":"repo","path":"%s"}\n' "$repo_json" \
>> "$OZ_SNAPSHOT_DECLARATIONS_FILE"

* [Handoff from cloud to cloud](/agent-platform/cloud-agents/handoff/cloud-to-cloud/) - Continue a finished cloud run; the prior session's workspace snapshot is what gets restored.
* [Self-hosting overview](/agent-platform/cloud-agents/self-hosting/) - Architecture decision guide for self-hosted workers, where customizing snapshots is most often needed.
* [Unmanaged architecture](/agent-platform/cloud-agents/self-hosting/unmanaged/) - Run `oz agent run` in CI, Kubernetes, or your dev environment outside the bundled image.
* [Oz CLI](/reference/cli/) - Full reference for `oz agent run` and `oz agent run-cloud`, including the `--no-snapshot` flag.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 [SUGGESTION] The CLI reference does not currently document --no-snapshot, so this related-page description sends readers to a page that cannot answer the flag-specific question. Either add the flag to /reference/cli/ in this PR or remove the including the --no-snapshot flag claim here.

Three suggestions from the Oz review on PR #105, all accepted:

1. Add a security caution after the declarations format section.
   Explicit warning that declared `file` paths are uploaded verbatim
   and `repo` paths upload the git diff (tracked + untracked,
   non-gitignored). Tells users to keep secrets, credentials, and
   API tokens out of declared `file` entries before copying the
   pattern.
2. Escape JSON metacharacters in repo paths in the bash template.
   The previous example printf'd `repo_root` straight into JSON; a
   path containing `"` or `\` would produce malformed JSON that
   Warp skips with a WARN. Added a sed pass that escapes `\` first,
   then `"`, matching the bot's suggested patch.
3. Drop the "including the --no-snapshot flag" claim from the Oz
   CLI Related pages bullet. /reference/cli/ doesn't document the
   flag today, so the claim sent readers somewhere that couldn't
   answer the flag-specific question. The flag is already covered
   on this page in the Disable snapshots section.

Co-Authored-By: Oz <oz-agent@warp.dev>
Copy link
Copy Markdown
Collaborator Author

/oz-review

@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 19, 2026

@hongyi-chen

I'm re-reviewing this pull request in response to a review request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

The "Prefer `repo` over `file`" rule said `repo` entries pick up
"tracked changes plus untracked files" while the security caution
right below said "tracked changes plus untracked, non-gitignored
files". The caution is the accurate one (matches
`git ls-files --others --exclude-standard` in
`app/src/ai/agent_sdk/driver/snapshot.rs::build_repo_patch`), so
tighten the rule to match.

Co-Authored-By: Oz <oz-agent@warp.dev>
Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR adds a new documentation page for customizing end-of-run workspace snapshots and wires it into the cloud-agent handoff sidebar and related self-hosting/handoff pages. I reviewed the supplied description, annotated diff, spec context, local docs guidance, and performed the supplemental security pass.

Concerns

No blocking concerns found. The changed content is documentation-only, the new internal links match existing docs paths, and the security review did not identify security issues.

Verdict

Found: 0 critical, 0 important, 0 suggestions

Approve

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

…ots docs

The two GitHub URLs the new snapshots page used were both pointing at
warpdotdev/warp-agent-docker, which is a private repo — anonymous
visitors get HTTP 404. Replaced both with link-free user-facing prose
and reworded all text mentions of the internal repo name.

Specifically:

* snapshots.mdx frontmatter description: "bundled warp-agent-docker
  image" → "bundled cloud agent image".
* snapshots.mdx intro paragraph: drop the link to the private repo
  root; refer to "Warp's bundled cloud agent image" instead.
* snapshots.mdx "When to customize" intro: replace "bundled
  warp-agent-docker image" with "bundled cloud agent image".
* snapshots.mdx env-var reference: same swap for
  OZ_SNAPSHOT_DECLARATIONS_SCRIPT description.
* snapshots.mdx "Write a custom declarations script": drop the link
  to the private snapshot-declarations.sh file; the sentence now just
  introduces the minimal pattern.
* snapshots.mdx: add a :::note callout under the script example
  describing what the bundled image's richer implementation does
  beyond the minimal pattern (OZ_SNAPSHOT_SCAN_ROOTS override, jq for
  JSON encoding, dedup against existing repo declarations) so power
  users know what's available without us pointing at private
  artifacts.
* unmanaged.mdx Tracking and observability cross-link: drop the
  "warp-agent-docker" qualifier.

Verified with grep: no more "warp-agent-docker" references anywhere
in src/content/docs/.

Co-Authored-By: Oz <oz-agent@warp.dev>
**Declared paths are uploaded to Warp.** `file` entries upload the file's contents verbatim, and `repo` entries upload the repo's git diff (tracked changes plus untracked, non-gitignored files). Before declaring logs, scratch files, or other agent outputs as `file` entries, make sure they don't contain secrets, credentials, API tokens, or other sensitive data.
:::

## Write a custom declarations script
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you think this is sufficient for a minimal pattern

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spoke offline about this, but I think it's cool to just include the whole script

Copy link
Copy Markdown

@harryalbert harryalbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!


The default snapshotting behavior is sufficient when your cloud agent runs use the bundled cloud agent image and operate entirely inside the assigned workspace. Customize snapshots when:

* **You use a custom Docker base image** that doesn't include the bundled `snapshot-declarations.sh` script.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit (and oo1): parts of this section are a little duplicative with the line 13's callout

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in bea343e — restructured the "When to customize snapshots" section so the bullets aren't duplicative with the intro paragraph anymore. The list now hits outside-bundled-image, repos/files outside the workspace, and dynamic scripted behavior as three distinct user-intent triggers.


* **You use a custom Docker base image** that doesn't include the bundled `snapshot-declarations.sh` script.
* **You run cloud agents on a self-hosted Direct backend** or as unmanaged `oz agent run` invocations, where the bundled script isn't on disk.
* **You want to snapshot a fixed set of repositories or files** outside the agent's workspace (for example, a sibling repo that the agent reads but doesn't `cd` into).
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can make this a little more expansive, because it doesn't have to be a fixed set. Because the user can write a custom script to generate the snapshot file and have warp run it, they can really script whatever dynamic or static snapshotting behavior they want

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in bea343e — replaced the "fixed set" bullet with a broader "dynamic snapshotting behavior" item that calls out that the script can implement any logic the operator wants (filter by git status, dedupe against a baseline, emit a fixed list, etc.), not just a fixed set of paths.


There are two ways to tell Warp what to snapshot at the end of a cloud agent run:

* **Script-driven** (default in the bundled image) - Warp invokes a declarations script that emits one JSON line per repository or file to snapshot. Use this when the set of repos isn't fixed ahead of time (for example, the agent may `git init` a new directory during its work).
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would probably be good to include the env var that points to the script here, so people know what to override? Or at least like reference it so that folks know that it's over-rideable before reading the script driven flow section

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in bea343e — the Script-driven bullet now names OZ_SNAPSHOT_DECLARATIONS_SCRIPT inline so readers know the path is overridable before they reach the Script-driven flow subsection. The Static bullet now names OZ_SNAPSHOT_DECLARATIONS_FILE for symmetry.

## Environment variables

* **`OZ_SNAPSHOT_DECLARATIONS_SCRIPT`** - Absolute path to the script Warp invokes at the end of each cloud agent run. The bundled cloud agent image sets this automatically. Set it yourself when running outside the bundled image.
* **`OZ_SNAPSHOT_DECLARATIONS_FILE`** - Absolute path to the JSONL file the script writes to (and Warp reads from). Warp sets this to a per-run path by default. Override it only when you want Warp to read from a static, pre-populated declarations file instead of running a script.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

folks should also set/override this from the OZ_SNAPSHOT_DECLARATIONS_SCRIPT so that warp knows where to read the final snapshot file from

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in bea343e — the OZ_SNAPSHOT_DECLARATIONS_FILE entry now spells out its relationship with OZ_SNAPSHOT_DECLARATIONS_SCRIPT: when the script var is set, Warp picks a per-run path and exports it to the script; users can also set/override the file path themselves so Warp knows where to read from, either to drive the static (no-script) flow or to pin both Warp and the script to a path they control.

* **Paths must be absolute.** Relative paths are rejected and logged as malformed.
* **Prefer `repo` over `file` for paths inside a repository.** Warp generates a git diff for each `repo` entry (tracked changes plus untracked files), so individual `file` entries inside that repo are redundant and dropped before upload. Including a `repo` entry is also more extensible than enumerating files.
* **Repos are diffed, not copied wholesale.** Only changed files are uploaded for each `repo` entry, so listing a large repository is cheap when the agent's changes are small.
* **`file` entries are for paths outside any declared repo** — for example, logs the agent wrote to `/tmp` or scratch files in `$HOME`.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems like a good call maybe

**Declared paths are uploaded to Warp.** `file` entries upload the file's contents verbatim, and `repo` entries upload the repo's git diff (tracked changes plus untracked, non-gitignored files). Before declaring logs, scratch files, or other agent outputs as `file` entries, make sure they don't contain secrets, credentials, API tokens, or other sensitive data.
:::

## Write a custom declarations script
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spoke offline about this, but I think it's cool to just include the whole script

…l example

Per Harry's Slack OK on showing the full script ("from a security POV,
definitely no issues with showing the entire script... any user who
cared could easily find the script by just running a cloud agent and
cat-ing it out"), include the canonical declarations script Warp
invokes inside the bundled cloud agent image in addition to (not
replacing) the minimal sed-based example.

Changes to snapshots.mdx:

* Keep the minimal sed-based example unchanged. It's a clean starting
  point for users adapting a custom script.
* Add a new "### The full bundled script" subsection right after the
  Direct backend tip. It introduces the canonical script in prose,
  then shows it verbatim in a second bash code block.
* Add a :::note flagging that OZ_SNAPSHOT_JQ defaults to /agent/tools/jq
  (an image-only path). External users adapting the script need to put
  jq on PATH or override OZ_SNAPSHOT_JQ.
* Drop the previous :::note that summarized what the bundled script
  did extra — the same information is now visible directly in the
  script.

Co-Authored-By: Oz <oz-agent@warp.dev>
Apply Harry's four outstanding review comments on PR #105:

- "When to customize snapshots" no longer duplicates the example list
  from the intro paragraph. Reframed around user intent rather than
  failure modes: outside-bundled-image, repos/files outside the
  workspace, and dynamic scripted behavior.
- Replaced the "snapshot a fixed set of repositories or files" bullet
  with a broader "dynamic snapshotting behavior" item that calls out
  that the script can implement any logic the operator wants, not just
  a fixed list.
- The "Script-driven" bullet under "How snapshotting works" now names
  OZ_SNAPSHOT_DECLARATIONS_SCRIPT inline, so readers know the script
  path is overridable before they reach the Script-driven flow
  subsection. The "Static" bullet now names OZ_SNAPSHOT_DECLARATIONS_FILE
  for symmetry.
- The OZ_SNAPSHOT_DECLARATIONS_FILE entry in the Environment variables
  section now spells out its relationship with
  OZ_SNAPSHOT_DECLARATIONS_SCRIPT: when the script var is set Warp
  picks a per-run path and exports it to the script; users can also
  override the file path themselves so both Warp and the script use a
  path they control (or to drive the static, no-script flow).

Co-Authored-By: Oz <oz-agent@warp.dev>
@hongyi-chen hongyi-chen merged commit e91ee49 into main May 20, 2026
8 checks passed
@hongyi-chen hongyi-chen deleted the oz/docs/snapshot-declarations branch May 20, 2026 00:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants