Skip to content

feat(device): run a directory of flows as a bundle - #235

Merged
riglar merged 12 commits into
feature/agent-devicesfrom
feat/device-run-bundles
Oct 19, 2026
Merged

riglar merged 12 commits into
feature/agent-devicesfrom
feat/device-run-bundles

Conversation

@riglar

@riglar riglar commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

Stacked on #234. Needs the API side, devicecloud-dev/dcd#1718 (flow bundles, Agent Devices 2.5b).

dcd device run [id] <dir> [--entry flows/login.yaml] [--env KEY=VALUE ...]

#232 refused a directory. Now:

  1. The directory is zipped, without .git, other dot-folders and node_modules. Entries are relative to the directory, so --entry is a path inside it. A directory with no .yaml file is refused.
  2. When the org's encryption default (or DCD_ENCRYPT) is on, the zip is encrypted, the same way dcd cloud encrypts flow zips, and its envelope is sent with it.
  3. POST /device/bundles/upload-url gives signed PUT URLs for the B2 copy and the Supabase fallback. The zip goes to both. A copy that fails is not claimed. If neither lands, the command fails.
  4. POST /device/bundles registers it with its SHA-256 and size. The API's 50 MB limit is checked before uploading.
  5. run { flowUploadId, flow? } runs it. Without --entry, every flow in the directory runs.

A single .yaml file is still sent inline, as before.

Tests

  • test/unit/device-bundle.test.ts: which files are bundled, the zip's entries, the SHA and size sent, a failed B2 copy not being claimed, encryption, and an empty directory.
  • device-command.test.ts: run <dir> --entry and the --entry checks.

pnpm lint, pnpm typecheck, pnpm test:unit (393 passing) and pnpm build pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_018tQfgpTsA9UhcopKoDezUA

riglar and others added 6 commits October 19, 2026 10:30
…ch and models

The first stages of the Agent Devices CLI (dcd plan 3.1 and 3.2).

- --json prints one envelope, {ok, session, data, error}, on success
  and on failure.
- Exit codes: 0 ok, 1 usage, 2 failed, 3 limit, 4 session ended or
  not found.
- The session id may be left out when exactly one session is open.
- start --app uploads a local build first; an https URL goes to the
  API's install-from-URL.
- Progress goes to stderr, with no spinner unless at a terminal.

Hidden from dcd --help until the API reaches production.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018tQfgpTsA9UhcopKoDezUA
Stage 3.3 of the Agent Devices CLI.

- inspect prints the compact screen; screenshot saves the frame to a
  file and reports its path.
- run sends one flow (a file or --yaml) with optional --env KEY=VALUE,
  and polls a flow that outlasts the API's wait. A failed flow exits 2.
- logs prints the app's recent log lines; --follow keeps printing new
  ones until the session ends.
- open opens the monitor at a terminal, and prints its URL otherwise.

Running a directory of flows needs an API change first and is refused
for now. openBrowser moves out of login.ts so device can share it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018tQfgpTsA9UhcopKoDezUA
Stage 5.3 of Agent Devices. Downloads what a session left behind into
./<session>-artifacts (or -o dir): recording.mp4, device.log, and per
action actions/NNN-screenshot.jpg and NNN-screen.json, numbered oldest
first. Follows every page. --links lists the signed links instead.
Files that cannot be fetched are reported, and the command exits 2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018tQfgpTsA9UhcopKoDezUA
logs --follow, a long run and start --wait reused the token resolved at
the start. A dcd login access token lasts about an hour, so a poll past
that failed with an auth error. Each poll now calls refreshAuth first;
an API key is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018tQfgpTsA9UhcopKoDezUA
dcd device run <dir> zips the directory (without dot-folders and
node_modules), uploads it to both copies through POST
/device/bundles/upload-url, registers it with its SHA-256, and runs it
by id. --entry picks one flow inside it; without it every flow runs.
The zip is encrypted when the org's default or DCD_ENCRYPT says so, as
dcd cloud's flow zips are. Needs dcd#1718.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018tQfgpTsA9UhcopKoDezUA
@claude

claude Bot commented Oct 19, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

…/device-inspect-run

# Conflicts:
#	src/commands/device.ts
#	src/gateways/device-gateway.ts
#	src/types/domain/device-session.types.ts
#	test/unit/device-command.test.ts
…/device-artifacts

# Conflicts:
#	src/commands/device.ts
#	src/gateways/device-gateway.ts
#	src/types/domain/device-session.types.ts
Base automatically changed from feat/device-artifacts to feature/agent-devices October 19, 2026 11:42
…/device-run-bundles

# Conflicts:
#	src/commands/device.ts
#	src/gateways/device-gateway.ts
#	src/types/domain/device-session.types.ts
@riglar
riglar merged commit 200ed43 into feature/agent-devices Oct 19, 2026
3 checks passed
@riglar
riglar deleted the feat/device-run-bundles branch October 19, 2026 11:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant