v0.5.0
Upgrade notes
Breaking changes
None for the standard upgrade path — the new docker-compose.yml you download below already contains the openclaw-secrets tmpfs block needed by the new SecretRef architecture.
If you maintain a custom docker-compose.yml (e.g. for a non-standard deployment, a different orchestrator profile, or a downstream fork), you must add this tmpfs block to the openclaw service definition before starting v0.5.0:
services:
openclaw:
tmpfs:
- /openclaw-secrets:mode=0700,uid=1000,gid=1000
# …rest of the service definitionWithout this, OpenClaw starts but cannot read its secrets, and every agent request fails with an authentication error.
Upgrade notes
v0.5.0 moves image version pinning from docker-compose.yml into .env. This is a one-time migration — after this, upgrading only means editing PINCHY_VERSION in .env and running docker compose pull && docker compose up -d.
-
Back up your database (as always):
docker compose exec db pg_dump -U pinchy pinchy > backup-$(date +%Y%m%d).sql
-
Fetch the new
docker-compose.yml:cd /opt/pinchy curl -fsSL https://raw.githubusercontent.com/heypinchy/pinchy/v0.5.0/docker-compose.yml -o docker-compose.yml -
Add
PINCHY_VERSIONto your.env:echo "PINCHY_VERSION=v0.5.0" >> /opt/pinchy/.env
-
Pull and restart:
docker compose pull && docker compose up -d
If you skip step 3, docker compose up fails loudly with a clear message telling you exactly what to add — this is by design, so a forgotten pin can't silently pull the wrong version.
Telegram: brief downtime on first start
OpenClaw detects the new SecretRef config format and hot-reloads. Telegram channels may be unresponsive for roughly 30 seconds during this reload. They recover automatically — no restart or re-configuration needed.
Recommended: rotate your API keys
Before v0.5.0, decrypted API keys were written into openclaw.json on disk. Docker volumes persist across container restarts, which means previous versions of openclaw.json (with decrypted keys inside) may still exist in volume history or backup snapshots taken before v0.5.0. After upgrading, rotate the keys at each provider:
- Anthropic — Settings → API Keys → revoke old, generate new
- OpenAI — API Keys → revoke old, generate new
- Google (Gemini) — Google Cloud Console → API Credentials
- Ollama Cloud — ollama.com/settings → API Keys
- Telegram bot — message @Botfather →
/revoke→/newtoken(only if you suspect exposure; revoking invalidates the previous webhook setup)
Then in Pinchy, go to Settings → Providers and re-enter each new key. Pinchy validates each one against the provider's API before saving. Optionally, delete old volume backups that predate v0.5.0 if you no longer need them.
This is a "nice to do" for most deployments, but if your server was ever compromised or you share volume backups with third parties, treat it as required.
Optional: scan audit logs for historical plaintext
If your compliance requirements demand evidence that no API keys were logged in plain text in your audit trail, run the bundled scan script:
docker compose exec pinchy npx tsx packages/web/scripts/scan-audit-logs-for-plaintext.tsIt checks audit log entries for patterns that look like API keys (Anthropic sk-ant-…, OpenAI sk-…, Google AIza…, Ollama Cloud, Telegram bot tokens). A clean result means your audit trail doesn't contain any key material.
Future upgrades
From v0.5.0 onwards, upgrading is just:
# Edit /opt/pinchy/.env → change PINCHY_VERSION to the new tag
docker compose pull && docker compose up -dThe docker-compose.yml only changes when we add new services or volumes, which is rare. Release notes will tell you when a fetch is needed.
What's new in v0.5.0
-
SecretRef architecture (RAM-only secrets) — API keys no longer touch disk. The
openclaw.jsonconfig file holds opaqueSecretRefpointers; the actual key material lives in a tmpfs volume (/openclaw-secrets/secrets.json) that exists only in RAM and is never persisted. Compliance-friendly default for regulated industries. See Secrets & API Key Storage. -
Web Search integration — connect Pinchy to the Brave Search API and grant agents per-tool access to search and page fetch. Per-agent filters for domain allow/deny, freshness, language, and region let you scope what each agent can reach. See Set Up Web Search.
-
Gmail integration — connect Google accounts via OAuth and give agents scoped email access: read, create drafts, or send. A guided wizard walks admins through the Google Cloud Console setup. See Connect Email.
-
Per-template model recommendations — agent templates now declare preferred model tiers (fast, balanced, reasoning) and required capabilities (vision, long-context, tools). When creating an agent from a template, Pinchy picks the best match from your installed models automatically.
-
Message delivery status — the chat interface now tracks whether each message reached the agent. A message dims briefly while the network round-trip completes; once the agent acknowledges it, the bubble returns to normal. If delivery fails, a "Couldn't deliver" notice appears.
-
Retry button — when a message fails to deliver, the agent doesn't respond, or a response stream drops mid-way, a Retry button appears directly below the failed message. Pinchy handles the right recovery action automatically — resend, re-trigger, or continue the partial response — depending on what went wrong. See Message Delivery Status & Retry.
-
Chat connection states with auto-recovery — the chat indicator now shows four distinct states (Starting, Ready, Responding, Unavailable) with a 2-second hysteresis that absorbs brief network hiccups. When the agent runtime becomes reachable again after a drop or settings change, Pinchy automatically refreshes the conversation history. See Chat Connection States.
-
Seat-cap enforcement for licensed deployments — Settings → Users now shows current seat usage (active users + pending invites) against the licensed
maxUserscap. The Invite button is disabled when at the cap, and the invite endpoint refuses to issue new invitations with auser.invite_blockedaudit entry. License expiry banner refreshes without a page reload. -
Integration delete with preflight — deleting an integration now shows a dialog with the agent usage count up front. If agents are connected, you can detach-and-delete in one step instead of hunting through every agent. The state machine handles in-flight deletions cleanly so a failed delete doesn't leave orphaned references.
-
Customizing your deployment — new guide documents the supported customization surface:
docker-compose.override.yml. Pinchy'sdocker-compose.ymlis owned by the project and replaced on upgrade — overrides go into the override file, which Docker Compose merges automatically and upgrades never touch. See Customizing Your Deployment. -
OpenClaw runtime updated to 2026.4.27 — the underlying agent runtime gets a significant bump. Notably: spurious gateway restarts on agent-config changes are eliminated (Pinchy now supplements the OpenClaw-managed
channels.telegramfields so the runtime sees no diff for Telegram-unrelated changes). The usage poller no longer runs immediately on connect, avoiding a CPU-boundsessions.listscan that was blocking the event loop during startup. No action required on upgrade.
Heads-up: Google template-model realignment
If you create new agents from a template with the Google provider, the balanced tier now picks gemini-2.5-flash instead of gemini-2.5-pro, matching Google's own tier descriptions (Flash is "best price-performance"; Pro is the reasoning tier). The fast tier picks gemini-2.5-flash-lite, and reasoning picks gemini-2.5-pro. Existing agents are unaffected — model IDs are only resolved at agent-creation time and never re-resolved on existing agents.
What's Changed
- feat(email): Gmail integration with guided OAuth wizard by @clemenshelm in #129
- feat: Web Search integration (Brave Search API) by @clemenshelm in #127
- fix: prevent gateway token drift between openclaw.json and gateway-token file by @clemenshelm in #166
- Scope 1: Release-process hardening by @clemenshelm in #168
- chore(ci): remove workflow_dispatch from pre-release.yml by @clemenshelm in #169
- docs: comprehensive docs audit and refresh (fixes #153) by @clemenshelm in #170
- fix(integrations): prevent silent permission loss on integration delete by @clemenshelm in #167
- fix: surface LLM provider errors in chat (fixes #152) by @clemenshelm in #173
- feat: env-var-driven versioning via PINCHY_VERSION (Scope 2) by @clemenshelm in #174
- feat(release): Scope 3 — Migration policy (Squawk lint + release-notes template) by @clemenshelm in #176
- feat(license): support JWT schema v1 (ver, maxUsers) with seat cap enforcement by @clemenshelm in #179
- feat(chat): message delivery status and retry button by @clemenshelm in #172
- feat(security): SecretRef for all openclaw.json credentials by @clemenshelm in #171
- chore(release): prep for v0.5.0 — deps + model bumps + checklist cleanup by @clemenshelm in #180
- docs(staging): add cloud-init-next snippet + Hetzner staging-instance section by @clemenshelm in #185
- fix(secrets): allowInsecurePath on secrets.providers.pinchy (release blocker for v0.5.0) by @clemenshelm in #186
- fix(staging): land prod-parity Caddyfile + installing.html (orphaned from PR #185) by @clemenshelm in #187
- fix(secrets): readGatewayToken falls back to openclaw.json (cold-start race) by @clemenshelm in #188
- fix(audit): allow validateGatewayToken to read token from openclaw.json by @clemenshelm in #191
- fix(chat): keep composer input enabled during reconnects by @clemenshelm in #192
- fix(telegram): allow Pinchy to read OpenClaw's pairing file by @clemenshelm in #195
- fix(openclaw): inotify + chmod-tick to win the secrets reload race by @clemenshelm in #201
- fix(openclaw-config): push config via WebSocket RPC instead of relying on inotify by @clemenshelm in #203
- fix(openclaw-config): single-restart push, not double cascade by @clemenshelm in #205
- fix(openclaw-config): fire-and-forget RPC push, never block on gateway restart by @clemenshelm in #206
- fix(model-resolver): type-constrain Ollama Cloud IDs against curated list by @clemenshelm in #208
- fix(ci): stop pruning released images, allow republishing tags by @clemenshelm in #212
- refactor(secrets): pinchy-odoo and pinchy-web fetch credentials via Pinchy API by @clemenshelm in #211
- fix(pinchy-email): add #209-style guardrails for credential handling by @clemenshelm in #214
- fix(chat): never render Send and Stop buttons together (#207) by @clemenshelm in #216
- fix(chat): stop cold-start green-indicator lie (#198) by @clemenshelm in #217
- fix(odoo-e2e): unblock Tier 2 prod-image switch, bypass Better Auth rate limit by @clemenshelm in #218
- ci: rebuild GHCR sha-* prune mechanism (#213) by @clemenshelm in #220
- feat(audit): PDF export and integrity-hash CSV column for compliance by @clemenshelm in #222
- fix(openclaw-config): break agent-create restart cascade (#193) by @clemenshelm in #219
- fix(chat): keep "Starting Agent" until initial message is rendered (#197) by @clemenshelm in #221
- fix(audit): address self-review feedback on export endpoint by @clemenshelm in #223
- fix(audit-export): address review round-2 findings by @clemenshelm in #247
- fix(integrations): serialize concurrent Google OAuth refreshes (#237) by @clemenshelm in #246
- refactor(agent-templates): split 1395-line file into focused modules by @clemenshelm in #248
- fix(openclaw-config): preserve plugins.allow order to break #193 cascade by @clemenshelm in #241
- fix(pinchy-web): pin resolved IP to close DNS-rebinding TOCTOU in SSRF guard by @clemenshelm in #224
- refactor(api-auth): centralize auth/role checks via withAuth/withAdmin (#228) by @clemenshelm in #255
- fix(use-ws-runtime): make message-status reducer generic over caller's shape by @clemenshelm in #242
- ci: close Docker Hub rate-limit gaps and mirror node base via gcr by @clemenshelm in #258
- fix(telegram-bots): apply RBAC visibility filter to bots endpoint by @clemenshelm in #240
- fix(auth): harden rate limits with explicit per-path customRules by @clemenshelm in #250
- fix(audit): redact email addresses in audit detail (#238) by @clemenshelm in #253
- test(infra): add real-DB integration runner; pilot invite-claim suite by @clemenshelm in #245
- refactor(openclaw-config): split 1097-line module into focused sub-files by @clemenshelm in #254
- fix(audit): log provider deletion with full cascade detail (#225) by @clemenshelm in #243
- fix(auth): tighten password policy to 12 chars + breach-list by @clemenshelm in #252
- fix(audit): stop swallowing audit-log failures via .catch(console.error) (#231) by @clemenshelm in #249
- test: replace wall-clock setTimeout waits with deterministic alternatives (#236) by @clemenshelm in #256
- feat(security): Origin/Referer CSRF gate for state-changing API routes by @clemenshelm in #251
- refactor(api): standardize request-body validation with Zod (#232) by @clemenshelm in #257
- fix(telegram-e2e): de-flake test 4 + skip multi-bot in CI by @clemenshelm in #265
- docs(claude): correct audit-log scope, plugin list, and project structure by @clemenshelm in #268
- fix(openclaw): lean down for container deployment + idempotency tests by @clemenshelm in #269
- chore(deps): bump openclaw 2026.4.12 → 2026.4.14 by @clemenshelm in #267
- fix: eliminate cold-start restart cascade (~117s → ~10s startup) by @clemenshelm in #270
- perf(openclaw): cut cold-start ~50s by pre-warming runtime deps and disabling unused plugins by @clemenshelm in #272
- fix(plugins): align pinchy-odoo + pinchy-web manifests with API-callback shape by @clemenshelm in #273
- fix(openclaw-config): immediate retry on OpenClaw stale-hash error by @clemenshelm in #276
- feat: layered plugin coverage guardrails + fix missing pinchy-web/email in production image by @clemenshelm in #275
Full Changelog: v0.4.4...v0.5.0