Repository navigation
feat(examples): give alchemy-cloudflare sessions a workspace, a bash tool and a Linux container - #50
Merged
K-Mistele merged 7 commits intoOct 1, 2026
Conversation
A fold chat host on Cloudflare deployed with Alchemy v2. Each session is a Durable Object named by its SessionId, with the fold event log stored in the object's SQLite. An alarm heartbeat keeps the object alive while a turn runs, and a turn cut off by a restart is nudged to continue (at most 3 times). HttpRouter routes reach the objects through a ChatSessions service. The model is OpenAI gpt-5.6-terra on medium reasoning, with the API key bound from the deploy environment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0ef41-7f9a-7c78-83e6-b468fe8c440e
Effect AI runs a tool handler with the services in scope where the turn runs merged over the ones its toolkit was built with, so the turn's win. A host whose request handling carries its own FileSystem shadowed the one the session started with: on Cloudflare, Alchemy provides Node's services to every Durable Object call, so the file tools read the Worker's empty temporary disk instead of the session's workspace. Each tool handler now merges the session's platform services last. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0f3fc-13b0-758f-a343-fae04e83a7a9
`@humanlayer/fold-agent/tools/files` exports read, write, edit and apply_patch (with a `fileTools()` bundle that `codingTools` now uses), and `@humanlayer/fold-agent/skills` exports the disk skill loader. Hosts such as Cloudflare Workers can use them without pulling in bash, the provider packages, or config loading. The read tool's TextDecoder now passes `ignoreBOM: false`, its default, because Cloudflare's type definitions require the field. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0f3fc-13b0-758f-a343-fae04e83a7a9
…d repos
Each session gets a @cloudflare/computer workspace: a filesystem with git
in a Computer Durable Object, hosted by a separate plain Worker and named
by the session's id. The first message's repos ([{ url, name?, ref? }])
clone into /workspace/<name> before the session starts; a failed clone
is a 422 and starts nothing.
The agent gets fold-agent's file tools and skill loader over the
workspace, through an Effect FileSystem backed by the Computer's file
methods. Skills load from each repo's .claude/skills and .agents/skills,
and the system prompt lists the repos.
The log route moves to GET /sessions/:id/log. Clones and file calls log
through Effect's logger, visible with `bun alchemy tail`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0f3fc-13b0-758f-a343-fae04e83a7a9
… sessions bash: the Computer's workspace gets @cloudflare/computer's worker shell, just-bash in a Worker started through a Worker Loader binding, which reads and writes the same filesystem as the file tools. The agent's bash tool keeps fold-agent's parameters and output handling: stdout then stderr, trimmed to the last 2000 lines or 50KB, failing with the output on a non-zero exit or timeout. It covers the common text commands and git; it cannot install, build, or run tests. Idle expiry: a session with no messages for 14 days deletes its workspace, then its own log, and restarts empty, so its id starts a new session. The deadline shares the object's alarm with the keepalive heartbeat. The workspace also sets its own backup alarm a day later, so it is deleted even when its session never deletes it. A session that wakes past its deadline skips resuming and waits for the alarm, so it cannot reach into the workspace mid-delete or bring it back empty. Also: - A resumed session counts only folders in /workspace as repos. - ChatSessions passes through failures other than RepoCloneError instead of replacing them with a SchemaError. - Shell commands log `workspace.exec`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0f3fc-13b0-758f-a343-fae04e83a7a9
…iner The bash tool gains a backend: the in-Worker shell, as before, or a Debian container attached to the Computer, where commands run as root in a bash login shell with git, node, bun, python3, ripgrep, fd and tmux. The session starts the container in the background when it starts, and deleting the workspace stops it. The container runs computerd from a fork of cloudflare/computer (K-Mistele/computer), built from a pinned commit, and the Worker uses @cloudflare/computer from a release of the same fork. The fork keeps gitignored files in the container instead of sending them to the Computer, so installs and builds don't fill its storage, and fixes the slow path lookup, disk syncs and uncached "not found" answers that made installs and test runs slow on the mount. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0f3fc-13b0-758f-a343-fae04e83a7a9
…n-with-durable-objects-and-alchemy-tyntlz HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0f3fc-13b0-758f-a343-fae04e83a7a9 # Conflicts: # bun.lock # examples/alchemy-cloudflare/README.md # examples/alchemy-cloudflare/alchemy.run.ts # examples/alchemy-cloudflare/package.json # examples/alchemy-cloudflare/src/Api.ts # examples/alchemy-cloudflare/src/ChatSession.ts # examples/alchemy-cloudflare/src/ChatSessions.ts # examples/alchemy-cloudflare/src/Keepalive.ts # examples/alchemy-cloudflare/test/Api.test.ts # package.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #48. Sessions in
examples/alchemy-cloudflareget a workspace and a way to run commands in it.What changes
@cloudflare/computer. The file tools and disk skills work on it.backend: "container"runs a command in a Debian container attached to the Computer, as root in a bash login shell, with git, node 22, bun, python3, ripgrep, fd and tmux. It runs onstandard-4(4 vCPU, 12 GiB). The session starts it in the background, and deleting the workspace stops it.The
@cloudflare/computerforkThe container runs
computerdfrom K-Mistele/computer, built from a pinned commit insrc/computer/container/Dockerfile. The Worker uses@cloudflare/computerfrom a release of the same fork, through the root catalog. The fork:node_modulesand build output) in the container instead of sending them to the Computer (computerd: let paths that match .gitignore stay on the container's disk instead of syncing to the Durable Object cloudflare/computer#179);COMPUTERD_DB_SYNCHRONOUSto skip SQLite's disk syncs;On Cloudflare (
standard-4),bun installin fold takes 147s andbun run testtakes 2m01s in the container; before the fork's fixes, tests timed out at 10 minutes.Testing
bun run typecheck,bun run lint,bun run format:checkandbun run testpass.🤖 Generated with Claude Code