Addresses four hardening items in one change:
- #8 Pin @anthropic-ai/claude-code to 2.1.114 via Dockerfile ARG.
`docker compose build --build-arg CLAUDE_CODE_VERSION=X.Y.Z` upgrades.
- #2 Move `client.kill()` from an `except CancelledError` branch into a
`finally` guarded by an `exited_cleanly` flag. Any abnormal exit path
(httpx timeout, generator GC'd, unexpected exception) now reaps the
open-terminal child — previously only asyncio cancellation did, so
dropped browsers left claude billing tokens until EXECUTE_TIMEOUT.
- #9 Per-chat CLAUDE_CONFIG_DIR=~/chat-<id>/.claude. Two concurrent
chats for the same OWUI user no longer race each other on a shared
~/.claude/. Safe to shard now that credentials live in the proxy
rather than .credentials.json.
- #1 sandbox/cleanup.sh installed at /opt/cleanup.sh. Not auto-run;
README documents dry-run-by-default usage via `docker compose exec`.
CHAT_TTL_DAYS and SESSION_TTL_DAYS control retention.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds `claude_agent_pipe_sandboxed.py`, a self-contained OpenWebUI pipe
that shells `claude --output-format stream-json` inside an open-webui/
open-terminal container instead of running the Claude Agent SDK
in-process. Each OWUI user gets a dedicated Linux account (mapped via
the X-User-Id header) with a per-chat workspace directory that persists
across turns and whose generated PNG/PDF/CSV artifacts are auto-inlined
into the chat.
Scaffolding under `sandbox/`:
- Dockerfile extending ghcr.io/open-webui/open-terminal with Claude
Code pre-installed system-wide (inherited by every provisioned user)
- docker-compose.yml + README covering standalone deployment
- Async HTTP client + stream-json runner for programmatic use
`sync_pipe.py` pushes the pipe to a running OWUI via the admin
functions API so iteration doesn't require manual repaste.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>