<?xml version='1.0' encoding='utf-8'?>
<rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" version="2.0">
  <channel>
    <title>Deploy Center</title>
    <link>https://deploycenter.app/</link>
    <description>Updates for Deploy Center</description>
    <language>en</language>
    <item>
      <title>Version 0.10.0</title>
      <pubDate>Thu, 12 Nov 2026 10:06:43 GMT</pubDate>
      <sparkle:version>0.10.0</sparkle:version>
      <sparkle:shortVersionString>0.10.0</sparkle:shortVersionString>
      <sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
      <sparkle:fullReleaseNotesLink>https://github.com/Pschmetzer/deploy-center/releases/tag/v0.10.0</sparkle:fullReleaseNotesLink>
      <description sparkle:format="markdown">- **Fixed:** "Vercel could not be loaded … jq: invalid JSON text passed to --argjson" after a single failed Vercel call. Under macOS's bash 3.2 an empty fallback became `{\}`; the list now loads with `partial` rows instead of failing, and `vercel_call` has a time limit and retries reads (never writes).
- CLI: `deploys plan [--when-green] [--json]` shows what `deploy-changed --yes` would start and roughly what it costs; `deploys price set`, `deploys budget set &lt;usd&gt; [--strict]` stops `deploy-changed` over budget unless `--force "why"`.
- CLI: the app's rules (`~/.config/deploys/rules.json`) are acted on: `deploys rules check`, hold rules in `deploy-changed`/`plan`, `deploy-changed --by-rules`, and `deploys schedule daily [HH:MM]` (opt-in, off by default).
- CLI: `deploys hooks install|uninstall|status` (keeps an existing pre-push), `verify` checks per project from `deploy-center.json`, `autofix --preview` (sends nothing), failure classes in `autofix status`, `ai ask`, `ai slow`, `watch --timeout`.
- CLI safety: `deploy` respects the deploy window; observer mode also blocks `autodeploy allow/revoke`; tab completion never runs project names; a non-integer `approvals` blocks instead of opening the two-person rule; `deploys logs` is always masked; `autodeploy-on --dry-run` is only passed to providers that support it.
- Providers: Netlify, Cloudflare, Amplify, DigitalOcean and Coolify follow the status contract, so `watch` and `deploy --wait` end; contract tests for all eight. Hook URLs over http only for exact localhost. **Changed:** a Vercel project with no remembered repo is not deployable (`repoUnknown: true`) instead of deploying from its live link. A Vercel production deploy with `--sha` is refused when the commit is not on the remembered branch (`DEPLOYS_VERCEL_ANY_SHA=1` to allow).
- Mac app: rule editor, Touch ID or password before risky steps (opt-in), site watch after going live, uptime per project, TLS certificate warning, migration tick before a live deploy, "critical" projects ask for the name, cost estimate and budget in the confirmation, health card, first-start guide, journal numbers (failure causes, monthly report), Spotlight (opt-in), a global hot key, colour-blind mode, quiet hours, project in its own window. A followed deploy resumes after a restart; status and cancel go to the right platform (they always went to Render).
- iPhone: build log with masked secrets, deploy history, Live Activity, Siri and Shortcuts (read-only), Spotlight, cancel build, Lock Screen and failed-builds widgets; an outage keeps the last rows; QR codes expire after 5 minutes. **Changed:** the GitHub token goes to the iPhone only with a new switch; it stays on for existing links, new links start off.
- MCP server: a client without elicitation is refused by default; Claude Code supports it, for Claude Desktop set `DEPLOYS_MCP_CONFIRM=client`. New read tools and `deploys_plan`. Claude Code plugin 0.3.0.
- Integrations: the GitHub Action can wait for builds (`wait`) and has `only`, `exclude`, `deploy: dry-run` and a risk gate; notify reaches Teams, Google Chat, Matrix and Pushover. **Changed:** the example workflows use `vars.DEPLOYS_VERCEL_TEAM` (rename `VERCEL_TEAM`).
- CI: release gate, Linux, iOS, Raycast and Docker jobs, app tests in English and German; the website publishes only after a green CI.
- App: the masker for "Copy for Claude" and prompts knows what the script's masker knows (`x-api-key:`, JSON `"password": …`, cookies, signed URLs, short Render and GitHub tokens, JWTs) and leaves "tokens: 12" alone; both maskers are tested against one list of lines (`tests/fixtures/mask/`). Settings → iPhone takes a read-only GitHub token of its own for the phone; it wins over the gh CLI's. One reader for `deploys autofix status` (rows and Settings). Menus and system texts follow the app language (`CFBundleLocalizations` en, de). Tests: the follow deadline on a short clock, and the test build checks concurrency strictly (warnings only).
- Site and docs: Impressum and Datenschutz use the shared stylesheet and the site's top navigation (with Docs and Guides), with sized icons; the Impressum's trademark note names all supported hosts and Anthropic (draft, legal review pending). SECURITY.md: the "What is sent where" table has no duplicate rows and lists the site check after a deploy.
- App: "Put this live now?" is one sheet for the footer, a row and the palette, with a real "Only when checks are green" checkbox (it was the alert's "don't ask again" toggle). The palette now asks with the same sheet as the window, checkbox included.
- App: the command palette builds its lines once when it opens (and again when demo mode switches) and orders them once per query, instead of on every keystroke and every store poll.
- App: the reload button loads every platform of the tab at once; the build log and the details mask names once per load or redraw; the saving picture is rendered once; a row reads its autofix state once.
- Costs: with a monthly budget set, the chart shows the budget per day and a line says what is left until the month ends (or how the pace compares).
- App: "Settings → …" in texts is built from the settings tab; a test checks that every `deploycenter://settings/…` link names a real tab.
- App: MainWindow.swift is split; the costs sheet, the setup screens and the row have files of their own (no code changed).
- App logic: the latest 30 messages survive a restart (Application Support); a list that fails with HTTP 401/403 or an expired login asks the doctor again, so the setup view appears; a failed `autofix sync` is logged instead of swallowed; Claude's answers render Markdown; Render service types and raw deploy states are translated; the widget's saving uses the same function and day as the costs panel; a new app language reaches the widgets; one rule for "failed" (widget, menu bar, Claude); savings reports moved from the preferences into files, decoded off the main thread; the Claude config is written with sorted keys; "Copy diagnostics" names the script version; one quit/restart dialog; dead code and unused imports gone.
- Tests: the test runner never writes into the real Application Support, Caches or log (`DEPLOYCENTER_DATA_DIR`, or a temporary folder for a binary without a bundle); new tests for ticking changed rows, waiting on two branches, the provider list after a failed read, cancelling `Tool.run`, the widget snapshot, allowance dates, the message store and the savings move.
- iPhone app, deploys and rollbacks: "Nothing new to deploy" before a build of the live commit; the rollback question names the commit, its message and date, and the app follows the rollback until the old version is live; a success or error tap when a deploy or rollback ends.
- iPhone app, list: auto-deploy shown on rows, in the details and as a line above the list; long press for deploy, rollback, open domain, copy the live SHA and the Render dashboard; VoiceOver's "Roll back" asks right there; live and newest commit both shown and copyable; an empty account explains the team id; a refused key (401/403) says so and offers the settings; a private repo without a GitHub token says so.
- iPhone app, start and network: the last list shows at once while the first load runs; data older than five minutes reloads on return; offline shows "Offline" with the time of the data and reloads when the network is back.
- iPhone and iPad: ⌘R reload, ⌘, settings, ⌘D deploy the selection; each window keeps its own selection; wide screens open the first project that needs attention.
- iPhone app, settings: "Test connection" shows the account, team and project count per platform; empty fields say when the Mac's key is used; a note when Background App Refresh is off or Low Power Mode is on. The welcome screen links to creating a Vercel token and a Render API key.
- iPhone app, QR code: a wrong or old code keeps the camera open with the reason.
- iPhone app, speed: GitHub reads use ETags (with a token, a 304 does not count against the limit), the second compare pass and the PR lookups run in parallel, the keychain is read once per key, dates use shared formatters; the background refresh has a time budget and shorter retry waits.
- iPhone app, notes: one note per project and event with a fixed id (no pile-up), more than three become one summary with "+N more".
- Widgets: a "Demo" tag on made-up numbers; on iPhone the time of the data, orange after six hours; the language comes with the snapshot, read once; the iPhone app reloads widgets only when what they show changed.
- shared: `DeployRule` holds the building/failed/waiting rule, `DeploySnapshot.localized` the language pick. `ios/test.sh` checks the rule, PR numbers, rollback targets, ETags and error texts against made-up answers on the Mac.
- ios/build.sh: `--archive` sets the build number from the commit count (or `BUILD_NUMBER`); `--run` boots an iPhone simulator when none is booted. The app is not offered as an iPad app on Mac or Apple Vision Pro.

- Digest issue: `@login`, HTML comments (a fake `deploys-approve` marker) and Markdown links in commit and PR titles are defused; the real approve marker stays the last line.
- notify and digest: `DEPLOYS_TZ` (for example `Europe/Berlin`) sets the day of "today" and of the issue title; default UTC.
- Ship-check example: the projects step added no `platform` to `deploys &lt;p&gt; json`, so waiting commits always showed 0; fixed and run in the tests. It runs on Claude Sonnet 5.5, pins the Action to `v0.9.1` and has a 15-minute job timeout.
- Examples use one variable name for the Vercel team, `DEPLOYS_VERCEL_TEAM`.
- MCP server: its version comes from `package.json` (no second copy in `server.mjs`); `scripts/bump.sh` no longer edits `server.mjs`, and a test checks that the Claude Code plugin and the MCP server carry the same version.
- `integrations/lib/projects.sh`: `changed_projects` asks `deploys changed --json` instead of rebuilding the ignore rule.
- VS Code: with nothing waiting, "Deploy…" moves to the end of the project menu as "Deploy again…".
- Raycast: lists show the last result at once (cached) and refresh in the background; failed builds get "Show Log" and "Copy Build Error" (secrets masked); unit tests for the parts without the Raycast API.
- CI: shellcheck and actionlint also cover the integrations and the example workflows; the widgets are built like a release; Xcode 16.4 is selected by name; new jobs build the Docker image and check the Raycast extension; the docs job runs `check-site.py` and ruff; `npm audit` for the MCP server; npm caches; no Homebrew self-update. The changelog reminder also covers `providers/`, `lib/` and `integrations/`.
- Dependabot also updates the npm packages of the MCP server, the VS Code and Raycast extensions, and the Docker base image.
- Tests: every file `deploys` sources is checked in the release tarball and the Homebrew formula; the provider tests run in parallel; MCP rollback of an unknown project.
- Docs: autofix never deploys (SAFE-DEPLOY.md, the autofix plist example); the CLAUDE.md block names `deploys deploy &lt;project&gt; --wait` for every platform; GUARD.md and AUTOFIX.md say they cover Vercel and Render only; the note about a hanging Render key is gone (it fails within a minute now).
- Issue and PR templates: the platform request lists platforms Deploy Center does not have yet, the bug form names the integrations, widgets and iPhone app, the PR checklist names all test scripts.
- CLI security: `deploy`, `verify`, `risk`, `ai explain|notes|ship` and `autofix --only` refuse names with `/ ? # &amp; %` before any lookup; Amplify ids (`&lt;appId&gt;/&lt;branch&gt;`) are taken with one `/` (`deploys amplify deploy-json app/main` works again). `cloudflare selftest` (one real build) is refused in observer mode.
- Team mode fails closed: with an observers list and no GitHub login, writes are refused ("gh auth login"; in GitHub Actions, `GH_TOKEN` must be a token that can read `/user`, not `github.token`). An approving review counts only when it approved the PR's last commit.
- Coolify: the token goes to a plain `http://` instance only on this machine, or when allowed on purpose (`deploys coolify set-url &lt;url&gt; --allow-http`, or `DEPLOYS_COOLIFY_ALLOW_HTTP=1`; an `http://` instance on another machine needs that once after updating). Deploy hooks: `http://` only for exactly localhost, 127.0.0.1 or [::1]. Netlify posts to a build hook without the API token, and only to `https://api.netlify.com/build_hooks/`. `open` opens only web addresses.
- CLI: provider commands that could not be reached now work: `deploys &lt;p&gt; on|autodeploy-on`, `&lt;p&gt; list`, `cloudflare selftest|account`, `coolify set-url`. An unknown verb lists the provider's commands; an unknown command names the nearest ones; `--help` ends with each enabled provider's commands. `providers enable` says the next step.
- CLI: `watch --timeout 30m` (exit 4), the time it ran, and the address once live; `deploy` without `--wait` prints the `watch` line; `deploy &lt;group&gt; --json` is one array (one project stays one object); `window` exits 2 when window.json cannot be read; `costs` says it is Vercel-only; `render status` takes a name; `vercel team &lt;id&gt;` and `vercel map` are checked with Vercel (`--no-check` to skip); `deploy-changed` starts a backend before the Vercel frontend of the same repo; after `--` nothing is parsed as an option.
- CLI robustness: Vercel reads are retried on 429/5xx/network errors; a non-login error of `vercel api /v2/teams` is shown as it is; `gh api`, `glab api` and `vercel api` stop after `DEPLOYS_CLI_TIMEOUT` seconds (90) with exit 124; a GitHub rate limit under 300 calls is named with its reset time; Anthropic 429/529 is asked again twice; Render logs past 100 lines are read page by page; Vercel's newest production attempts are read past the first 100.
- CLI internals: `_meta` of the opt-in providers is printf (no jq needed); `meta_flag`/`meta_str` accept spaces; one way to find the script's folder (no `readlink -f`); enabled providers read once per process; fewer CLI and API calls (Vercel rollback and doctor, Render owner id cached, Netlify/DigitalOcean ids passed through in `watch`); no functions defined inside functions.
- Docs: docs/CLI.md covers every command, the commands with JSON, an exit-code table and the environment variables; README-CLI.md has the full requirements and a working CI example for Vercel; docs/PROVIDERS.md lists all providers and the `_has`/`_status`/`_meta` rules.
- Tests: observer mode and name checks for every writing or name-taking command, help against the case labels, doctor key uniqueness, and the fixes above; team tests no longer depend on the time of day.

- pre-push hook: reads `deploys list --json`, so it warns for every platform that is on, and for GitLab remotes (`gitlab.com/group/sub/app`) too. An older CLI without `list` still gets the Vercel and Render lists.
- Status page: `platform/name` works for every platform, not only `vercel/` and `render/`.
- Badges: a name on two platforms gets one badge per platform (`vercel-web.svg`, `netlify-web.svg`); every other name keeps `&lt;name&gt;.svg`.
- Webhooks (notify, digest, status page): `http://` only to localhost, 127.0.0.1 or [::1]; anything else needs `https://`.
- Digest: GitLab merge requests get their title, author and labels through `glab`.
- VS Code: a timeout ends the CLI with everything it started; fuller secret masking; "Show log" opens a read-only document; a settings change during a refresh is not lost; GitLab repos match with host and subgroups.
- Raycast: every platform, `platform:name` for twins, "Deploy All" as one `deploy-changed` run (only when it matches the confirmed list) and off after a run, a timeout ends the CLI's children, and a "401" in a commit is no login error. Publishing uses the locked `ray`.
- `scripts/check-public.sh`: also tokens (GitHub, Anthropic, GitLab, AWS, Slack), private key blocks, email addresses, and words from `~/.config/deploys/private-words`; `--stdin` checks commit messages, which CI now does for every pull request.
- Website workflow and the example workflows pin actions by commit SHA and check out with `persist-credentials: false`. The Docker image pins its node base by digest and installs `gh` from GitHub's apt repo.
- docs/CLAUDE-CODE.md: the suggested deny rules cover every command that deploys, rolls back or turns automation on.
- Settings: new tabs Projects (hidden projects plus pinned, notes, check paths, roll back on failure and ignored build triggers, each with a reset), Costs (budget as a currency field with a stepper and a line saying when the warning comes) and iPhone; the ⌥⌘K hot key moved to General. Each tab has its own height, the window keeps its place, and tabs with options get "Reset to defaults …" (asks first, never touches keys or project data).
- Settings: links into Settings open the right tab ("Open Settings" for hidden projects, the Claude nudge, the Autofix toast, which also scrolls to Autofix, without the private `showSettingsWindow:` selector). New link `deploycenter://settings/&lt;tab&gt;`.
- Settings fixes: notification and login-item hints are read again when the app becomes active; "Open at login" no longer registers twice after an error; a stored value a picker does not offer becomes the nearest one; "Copy diagnostics" has a line per platform, GitLab and Autofix; the Help text names GitLab and every platform; Help lists the keyboard shortcuts.
- Settings → Platforms: platforms the window cannot show yet say "command line only" and cannot be switched on; planned ones sit in a folded "Planned" list without a switch; the locked last switch says why; after a switch "Vercel: on, 35 projects loaded", a failure offers "Try again"; Vercel and Render show whether they are connected.
- Settings → Deploy: "Ask before a single deploy" (on by default) for the row menu and the palette alike.
- Demo mode: View → Demo Mode (⇧⌘D) and a DEMO badge in the window. The output of Autofix, Claude, Team and the guard shows stand-ins; the iPhone QR code cannot be shown in demo mode and closes when it is turned on, and its window is left out of screenshots and screen sharing.
- The menu bar and `deploycenter://select?project=` show exactly that project (by platform when one name is on two; `platform:name` works in the link). A link only shows: it never ticks or starts anything.
- "Changed" counts leave hidden projects out everywhere. One compare link for GitHub and GitLab (`Item.compareURL`).
- Status banner: the status pages come from the provider data (Netlify, Cloudflare Pages, DigitalOcean and others, plus a `statusPage` the script may report), only for platforms that are on.
- Latest messages: a line about a project opens its build log; "Clear" empties the list.
- GitHub budget spent: the app reloads by itself shortly after it resets.
- Costs and build triggers say "As of …" when the last read failed and the values are older.
- The guard's "Run now" reloads only the platforms that are on, in parallel; platform names come from the provider labels ("DigitalOcean App Platform", not "Digitalocean").
- Autofix: "Copy prompt" says why when it fails.

- `./build.sh --install` builds the widgets too when a signing identity is set, so a local install no longer removes the widgets from ~/Applications.
- Autofix: "Claude is fixing it" no longer sticks. The app runs `deploys autofix sync` (new: records merged, closed or open fix PRs, never fires) every few minutes while a hand-over is open, so a merged fix shows "Fix merged – deploy now" even when the 10-minute job is not running. `autofix --only` syncs its project first.
- Autofix: 90 minutes after a hand-over with no PR the row says "No fix PR from Claude – see session" (a cause outside the code, say) and links the session, instead of "fixing" for good.
- `autofix status` reports `scheduled` only when launchd has the job loaded; `autofix sync` loads a job file launchd dropped again.
- CLI tarball and Homebrew formula ship `lib/` next to `deploys`, so team files, the two-person rule, observers, GitLab, `simulate` and `ledger` work after install.sh or `brew install`.
- MCP server: build logs are masked (tokens, keys, passwords, emails) before the agent sees them; arguments are checked against each tool's schema, an unknown or wrong one is an error; `deploys_logs` keeps the real end of a long log; `deploys_changed`/`deploys_status` are never cut in the middle of the JSON (whole entries are left out, with `truncated`).
- Release: `release.sh` refuses untracked files too (build.sh takes `app/*.swift`, `providers/*.sh`, `lib/*.sh` by glob), creates the GitHub release as a draft and publishes it only after the uploaded files match their SHA-256, gives the appcast the app's own minimum macOS (one `MIN_OS` in build.sh), and fails instead of shipping an app without the MCP server. `build.sh` bundles a `.mcpb` only when it is in git, signs only `deploys` on its own in both branches, and `--install` copies next to the old app and swaps, so a failed copy keeps it. `scripts/bump.sh` also sets the MCP server and Claude Code plugin versions and fails when a site line is not found.
- MCP server: `deploys_deploy` and `deploys_rollback` work on every platform (`&lt;platform&gt; deploy-json`) and take `platform:name` for a name on two platforms. A client with elicitation asks the human itself before each one. At most `DEPLOYS_MCP_MAX_DEPLOYS` (default 3) starts per server process, and `DEPLOYS_MCP_ALLOW_PROJECTS` limits which projects. A timed-out start says the build may be running, and the next try reads `status` first. Notes, explain and logs come framed as `&lt;untrusted-data&gt;`. Ending the server stops the `deploys` it started.
- GitHub Action: the deploy step reads `deploy-changed --yes --json` instead of parsing a text line (an answer that is not JSON fails the step). `deploy-on-marker.yml` runs one at a time (`concurrency`).
- Digest: when nothing waits any more, open digest issues are closed, so a later `deploy-approved` label cannot deploy the morning's list. **Changed:** `approve-deploy.yml` reads the list from the digest's own newest, unedited comment (`DEPLOYS_DIGEST_BOT`, default `github-actions[bot]`), not from the editable issue body; it accepts `platform:name`, reads every platform (`deploys list --json`), refuses one platform of a name that is on two, and passes `repo: "*"` to the action (its projects deploy from app repos).
- GitHub Action: with `deploy: true` only the projects of the workflow's repository are started (new input `repo`, `*` for every repo); it fails and starts nothing when that cannot be made sure.
- Claude Code plugin: the push reminder also works for GitLab remotes (subgroups too) and for `cd dir &amp;&amp; git push` and `git -C dir push` (the hook no longer has an `if: Bash(git push *)` rule, the script filters). The skills deploy every platform with `deploys deploy &lt;p&gt; --wait`, forbid `--force`, `autodeploy allow`, `guard` and `autofix --only`, and `deploys-ship` no longer calls a project "already live" when `changed` could not read it. The MCP example config runs the server the app ships, no clone needed.
- Claude Code plugin: the push reminder ignores `git stash push`, `--dry-run` and rejected pushes, and reads the right repo for `cd dir &amp;&amp; git push` and `git -C dir push`.
- `examples/daily-deploy.yml` installs the checked release tarball (with providers/ and lib/), pins the vercel CLI and sets `permissions:`. CI runs `integrations/tests/run.sh` with `REQUIRE_ALL=1`; a skipped part is reported as skipped, not passed.
- Netlify, Cloudflare Pages, Coolify, DigitalOcean and Amplify keep the provider contract: `&lt;p&gt; has` prints the id, `_status`/`_latest` give `id&lt;TAB&gt;phase&lt;TAB&gt;state`, so `deploy --wait`, group deploys, `watch` and `verify` work for them. The contract tests now run for all five. **Changed:** a Cloudflare project's id is its name (the API paths need it), not the UUID; `netlify logs` exits 1 because Netlify has no build log API.
- `deploys deploy &lt;p&gt;` and group deploys respect the deploy window like `&lt;p&gt; deploy`; forced starts go to the journal.
- Observer mode: `deploy-changed … --yes` is refused wherever `--yes` stands; `autodeploy allow|revoke` and `verify` (unless `--no-rollback`) are refused too.
- `--when-green` no longer passes `--sha` to hosts that cannot build a given commit; it says the branch's newest commit is built.
- Projects without a git repo (image services, unsupported git hosts) are `noRepo`, not "state unknown": `changed` no longer exits 1 for them on every run.
- Render: `render_last_of` has timeouts; a keychain that cannot be read makes `changed` fail ("keychain could not be read") instead of "Nothing to deploy".
- App: hidden projects are never ticked or deployed; ⌘A ticks only the rows the search and filter show.
- App: single deploys (row menu, retry, palette, commit deploy in details) check the deploy window and "only when green" like the batch.
- App: "Deploy to production …" in the row menu asks first, like the palette; "Stop all" asks with the number of deploys it ends. The confirmation names the platform under "All" and marks risky projects.
- App: an empty reason for "Deploy anyway" says that nothing started; rollback and build log are offered only where the platform has them; "Deploy all changed", the palette and the footer's "+2 on …" use enabled platforms only; tab counts and "Changed only" leave hidden projects out.
- App: ⌘K is in the View menu; the ⌥⌘K hot key opens the palette in one main window and its arrow keys no longer act in Settings; a hot key taken by another app is reported and the switch goes back off. The palette says when more than 60 lines match.
- App: GitLab repos get GitLab links (merge requests `!12`, compare) and texts; the details compare against the branch head when the branch is unknown, show "reloading failed" instead of a silent stale view, and list 30 waiting commits first. The monorepo hint counts Vercel projects only and its Ignored Build Step compares with `VERCEL_GIT_PREVIOUS_SHA`.
- App: cancelled deploys show grey "cancelled" instead of a red failure; a failed row shows the first line of its error; "Copy the error" masks tokens; release notes, "Copy for Claude" and "Copy the error" use the stand-ins in demo mode.
- App: a closed provider notice stays closed across launches; "Ignore" on a build trigger can be undone; load errors have Details and Copy; the folded notice line shows how urgent each one is; the search marks domain and source matches and ignores accents; a menu-bar click shows exactly that project; repo headers show project and commit counts.
- App: the monthly cost pace counts whole days only (today is marked "so far" in the chart); the costs list the projects by cost; "Copied ✓" resets and a failed PNG save is reported.
- App: VoiceOver names the build log and says what PR and commit buttons open; error lines carry a mark with "Differentiate without colour"; banners follow "Increase contrast"; toasts and notices only fade with "Reduce motion".
- App: a build past 40 minutes is not shown as failed and keeps its row locked (polled every 30 s, at most 12 hours), so a second paid build cannot start by mistake.
- App: waiting for green CI no longer holds a build slot and can be cancelled; the auto-rollback is skipped when a newer deploy has started; allowances for all platforms or all projects show their badge; demo mode hides the favicon in details; "Copy" in the build log masks secrets (⌥ copies the raw log).
- App: the menu bar list leaves out hidden projects; waiting commits are counted per repo and branch (staging on `develop` and production on `main` no longer merge); the stale alarm skips projects that cannot deploy; the budget pace leaves out the unfinished day; a run's summary counts skipped rows; a second "Undo" toast (a rollback's Cancel) waits instead of replacing the first; a frontend held back by its failed backend is "skipped" in the journal, not "failed"; plural fixes ("1 project").
- App: observer mode keeps the ticks when it refuses a deploy, refuses rollbacks, does not tick merged fixes, and is read again hourly (no need to open Settings → Team). Errors of "turn off auto-deploy", a failed doctor after saving the Render key and a failed `guard status` no longer vanish or reset the state; a failed `providers --json` keeps the last list instead of switching platforms back on, and a switched-off platform's saved list is not shown at start.
- App: a new refresh interval and more parallel builds take effect at once; no doubled reloads after wake; reloads pause while the screens sleep and run half as often in Low Power Mode (costs and strays wait); status polls back off to every 15 s in the middle of a long build; no App Nap or idle sleep while deploys run. Render's `succeeded` records the build time and marks a rollback as behind. The daily reminder shows with the app in front. "Open Settings" in the Autofix toast works on macOS 14+; "Autofix not set up" is read from the exit code (`ToolError.exitCode`).
- App: the script is run without blocked threads and answers even when a detached child keeps a pipe open; `claude` (Settings → Claude) and `gh auth token` (iPhone link) end with their whole process tree at the timeout. The error log masks secrets, is written off the main thread and cannot crash the app on a full disk (journal too). The masker knows Stripe, GitLab, npm, Google, AWS session keys, `--token` and private key blocks.
- App: demo mode scrubs names in Mac notifications too. GitLab repos get GitLab compare links; an `{"error": …}` answer shows its text. Reconnecting Claude Code restores the old entry when the new one fails; an MCP entry pointing into a moved app is reported; only the newest three Claude config backups stay. iCloud Keychain is written only when a key changed. Platform names in simulator and ledger use the provider's label; the German estimate text follows the script's method. Favicon lookup reads at most 64 KB of the front page. Autofix, guard and team status tolerate missing fields.
- iPhone: a second tap cannot start a second deploy; demo deploys need no passcode; rollback refuses when the live deploy is unknown instead of guessing; a QR import keeps keys the QR code leaves empty; a rewritten history or a compare error shows "count unknown" instead of "0 commits".
- iPhone, reading: API answers are no longer cached (a fresh push could hide behind GitHub's `max-age=60`); GitHub's 403 rate limit and `Retry-After` are honoured, with the reset time shown instead of "HTTP 403"; the Vercel team is resolved once, not on every status poll; several Vercel teams without a team id say so instead of silently showing the personal account; a failed deployments read, a list cut at 1000 and GitLab/Bitbucket services ("only GitHub repos are compared") are shown, not swallowed.
- iPhone, deploys: a Vercel deploy that is ready but held off the domains after an Instant Rollback says so instead of "is live"; raw states like `build_failed` are shown in words; the widget's "since" for building or failed projects is the start of the attempt.
- iPhone, background: the refresh uses the app's own store (the list is fresh on return), replaces nothing when iOS cuts it off, keeps what it has seen in Application Support instead of Caches, and sends no notes when there is nothing to compare with yet.
- iPhone, language: texts, dates and the system dialogs (camera, Face ID, now also in German) follow the same language; the widget gets it from the app.
- iPhone, privacy: QR codes older than two minutes are refused; token fields no longer offer to save to Passwords; optional "Unlock on open", which also hides the list in the app switcher; "Remove all keys from this iPhone" (the Mac keeps its keys); a warning when the GitHub token can write; widget project names are hidden while the device is locked; the widget snapshot carries no commit texts; two projects of the same name no longer share a widget row id.
- iPhone, settings: changed fields are not lost by swiping the sheet away (Cancel discards), and a keychain that refuses a key is reported.
- iPhone, accessibility: notes are announced by VoiceOver and errors stay until closed (with a close button); rows have Deploy, Roll back and Open domain actions; the status icon is not read; texts name Face ID, Touch ID or the code as the device has it; the QR scanner explains itself and gives haptic feedback; "Updated …" and "Waiting since" keep ticking; the widget reads as one sentence and scales with the text size.
- Docs and site: README, FAQ and guides no longer call built features "coming"; the site takes its version from `VERSION`; SECURITY.md and UNINSTALL.md list every data flow, job and keychain entry. `install.sh` runs from `main()` (a cut-off download installs nothing) and stops on Ctrl-C.
- CLI: `deploy --wait` exits 3 (not 1, "did not go live") when the platform could not be asked, and follows the newest deploy when a start has no id yet (Netlify). `changed` with no platform on and set up is an error pointing to `deploys providers`, not "every project is on its newest commit"; `--platform` with an unknown name is refused.
- CLI: a keychain that cannot be read is named for Netlify, Coolify, DigitalOcean, Cloudflare and Amplify too, instead of their "no token".
- CLI: `verify`, `risk` and `ai` take `p:name`. **Changed:** `verify` exits 3 when nothing was checked (unknown project, not live, no address, a wrong option), so 1 always means "rolled back"; with `--path`, a 4xx fails the check too, and redirects are followed.
- CLI: `guard schedule`/`guard status` say "on" only when launchd has the job loaded, and load a dropped one again. Two projects of one name on one platform name their ids instead of suggesting `p:name` again. The name cache forgets deleted projects. The journal writes a provider's label ("Netlify"), not its id.
- CLI: keys piped to `set-key`/`ai set-key` lose a trailing CR and surrounding spaces; spaces, quotes or a backslash inside are refused. `logs &lt;p&gt; 0` is refused (it printed the whole log), `history` takes 1 to 100, `open` only `--dashboard`. Tables work without `column` (an awk fallback).
- CLI: `ignore vercel:api` leaves out only that platform's project. A name that is a group and a project is refused by `deploys deploy`; `group:&lt;name&gt;` picks the group.
- Vercel: deploys from GitLab or Bitbucket get their commit (`lastSha`, rollback, history, savings). Turning auto-deploy off keeps a link whose repo cannot be written down (Bitbucket) instead of losing it; turning a GitLab one back on points to the dashboard. `vercel deploy --wait` gives up like `watch` (exit 3) instead of asking for ever. Vercel and Render `deploy-json` refuse unknown options instead of deploying the newest commit.
- Bug scan: "Find bugs with Claude" (row menu and details) runs the Claude Code CLI on this Mac against the repo, fixes up to five real bugs, runs build and tests, and opens one PR with a report. Never merges or deploys. `deploys scan start|status|list|log`. See docs/SCAN.md.
- Security check: OSV-Scanner, gitleaks and Semgrep on a repo, free and local (`deploys check start|show`, "Security check" in the row menu and details). "Fix with Claude" hands the package and code findings to a bug scan (`scan start … --findings &lt;id&gt;`). Secrets are redacted, never stored as values, never sent to Claude or put in a PR; the app lists them as keys to rotate.
- `deploys` refuses every command that changes something when `lib/team.sh` is missing but this Mac uses a shared deploy-center.json (team repos, overrides.json or a cached shared file): an install without `lib/` no longer skips the two-person rule and the observers list. Reading still works.
- The shared `window` and `health` of deploy-center.json now count in the CLI: a deploy outside a project's allowed window (in its `tz`) is refused, or skipped by `deploy-changed`, unless `--force "why"` (journaled); `verify` without `--path` checks the shared `health` path. An unknown time zone is an error, not UTC.
- Guard and allowances cover every platform that can turn auto-deploy off (Netlify, Cloudflare, Coolify, DigitalOcean, Amplify), not only Vercel and Render. **An already scheduled guard now also turns auto-deploy off there** when it is on without an allowance. A switch-off that leaves auto-deploy on (Netlify waiting for its netlify.toml line) is reported as failed, not as done. Netlify gets no allowance, since auto-deploy cannot come back on from here.
- `deploys ci` and `deploy-changed --when-green` read every page of check runs (a red check past the first 100 is red), and GitLab pipelines; a GitLab repo nobody here can read, or a host deploys does not know, is skipped at once instead of waiting 30 minutes. `details` counts checks over every page too.
- GitLab: `risk` and the `risk` of `changed`/`pending` work for GitLab repos; a GitLab host with a port (`git.example.com:8443`) is asked on that port; `deploys gitlab set-token` (trimmed and tried before it is saved, like `render set-key`) keeps the token in the keychain instead of `GITLAB_TOKEN` in the shell profile, and `gitlab forget-token` removes it.
- `changed` says why a branch head is unknown (rate limit, not logged in, no such repo or no access, host not reachable) instead of always "is gh installed and logged in?".
- The two-person rule says when GitHub could not be read to check approvals, instead of "Found none".
- `details` (and `risk`, `ai`) without a branch use the repo's default branch, never a silent `main`; when it cannot be read, `details` says so.
- `deploys logs --masked` hides keys, tokens, passwords and email addresses (the same mask as autofix), for logs that go to an agent or a model.
- `doctor` puts the Netlify, Coolify, DigitalOcean, Cloudflare and Amplify fields under their provider name (`netlify.tokenOk`), so one provider no longer overwrites another's. Vercel, Render and hook keys stay at the top.
- `triggers` finds workflows that deploy to Netlify, Cloudflare, DigitalOcean, Amplify or Coolify, in the repos of every platform that is on.
- Coolify: Ctrl-C during a deploy with `--sha` puts the app's commit back instead of leaving it pinned for later auto-deploys.
- Savings (`simulate`, `ledger`) no longer ask Render about another platform's projects: a provider without its own `&lt;p&gt;_builds` is marked unsupported.
- Open pull requests: a full page (100) is marked `openPartial`, a floor and not the exact count. `xargs` no longer runs once on empty input on Linux. The launchd job files escape `&amp;` and `&lt;` in paths.
- iPhone app: tokens are stored in the app's own keychain group, not the team group the Mac link uses (which other apps of the same team could read); keys an older version stored there move over on first read.
- MCP server: `deploys_deploy` deploys the branch head the human confirmed, by its commit SHA (`--sha`) where the platform can pin one, and the question names that commit; a push between the question and the start is no longer deployed with it.
- Masking: the MCP server and the VS Code and Raycast add-ons now also mask cookies, signed-URL signatures (`sig=`, `X-Amz-Signature=` …) and `-key`/`AccountKey=` names, as the CLI does. One shared fixture (`ios/Tests/fixtures/mask-in.txt`) is checked against all of them, and `ios/Tests/run.sh` checks that `mask-out.txt` is still what `af_mask` prints.
- Action: the vercel CLI it installs is kept in the Actions cache per version and runner type, so later runs skip the npm install.</description>
      <enclosure url="https://github.com/Pschmetzer/deploy-center/releases/download/v0.10.0/DeployCenter-0.10.0-universal.zip" length="15750440" type="application/octet-stream" sparkle:edSignature="ghPl9atTd2IPUV5h5DvC3TMKyuXay0dgbkbwZbIEpO9FZk2Ji3qz1MDetAybxER5EkIrlMLT0y/D2j1JUgtPAA==" />
    </item>
    <item>
      <title>Version 0.9.1</title>
      <pubDate>Tue, 10 Nov 2026 09:17:27 GMT</pubDate>
      <sparkle:version>0.9.1</sparkle:version>
      <sparkle:shortVersionString>0.9.1</sparkle:shortVersionString>
      <sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
      <sparkle:fullReleaseNotesLink>https://github.com/Pschmetzer/deploy-center/releases/tag/v0.9.1</sparkle:fullReleaseNotesLink>
      <description sparkle:format="markdown">- Settings → General → Language: English, Deutsch or the Mac's language (the default). The app restarts to switch; the widgets follow it.</description>
      <enclosure url="https://github.com/Pschmetzer/deploy-center/releases/download/v0.9.1/DeployCenter-0.9.1-universal.zip" length="13294717" type="application/octet-stream" sparkle:edSignature="T79BCwHpbxrAt8a/JexRXdc/40iGo+mNeFaUq43LgbrlWbIA8n5o/DE6ydv28o3VOp7aYXnLt0Gnnn51rBhjAA==" />
    </item>
    <item>
      <title>Version 0.9.0</title>
      <pubDate>Tue, 10 Nov 2026 08:14:58 GMT</pubDate>
      <sparkle:version>0.9.0</sparkle:version>
      <sparkle:shortVersionString>0.9.0</sparkle:shortVersionString>
      <sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
      <sparkle:fullReleaseNotesLink>https://github.com/Pschmetzer/deploy-center/releases/tag/v0.9.0</sparkle:fullReleaseNotesLink>
      <description sparkle:format="markdown">- `deploys status --json` carries the shared `phase` of each project. VS Code extension 0.2.0: every platform, not only Vercel and Render; failed and building from `phase`; a name on two platforms is passed as `platform:name`; a hint when no project matches the folder.
- Observer mode also refuses `guard` and `autofix --only` (without `--dry-run`); both change something. An approval check on a GitLab-linked Vercel project says that approvals are read from GitHub only.
- Command palette: in observer mode (Settings → Team) it offers no deploy, rollback or "deploy all changed", like the window.
- Ask Claude → Explain this failure: its button is now "Fix with Claude", the same as on the row (same caps, setup offer and toast).
- Updates via Sparkle 2: the app reads https://deploycenter.app/appcast.xml once a day (Settings can turn it off) and on "Check for Updates …", accepts a download only with a valid EdDSA signature and the same Developer ID, and installs once no deploy is running. Replaces the old GitHub release check and "Update now". The Homebrew cask says `auto_updates true`.</description>
      <enclosure url="https://github.com/Pschmetzer/deploy-center/releases/download/v0.9.0/DeployCenter-0.9.0-universal.zip" length="13164204" type="application/octet-stream" sparkle:edSignature="joElfiUlxnrRF7g2au6dtOgrboVH0QFZ4+fxdVwdVouU7oOJOyx2SDlNinye8AiwX5Bg83pH+7d1wg+cS0AnDw==" />
    </item>
  </channel>
</rss>
