Changelog

Release history for the sfp CLI — what changed in each version.

The sfp CLI carries its own version line, separate from sfp server's. Releases are published to npm as @flxbl-io/sfp and in the sfp docker images; see Install sfp. Under codev the CLI runs on the server, at the server's release.

Only releases that change the CLI are listed. A version absent from this page shipped no CLI-facing change.

September 2026

v52.19.0 — September 16, 2026

  • sfp server update logs the Hatchet worker-assignment commands it runs over SSH against a remote host, and their output, at debug level rather than info. A command that exits non-zero is still reported at error level.
  • sfp server update names the worker-assignment pause before it runs, and on resume reports how many workers had their assignments restored and how many registrations the restart replaced. That report is printed whether the update finishes or fails.

v52.18.2 — September 15, 2026

  • sfp server callback post --context-id takes the UUID of a callback context held on the server, in place of the inline JSON on --context. The two flags are mutually exclusive and exactly one is required; the command reads the context from the server with the server URL and application token before it posts.
  • sfp server callback post fails before posting on a --context-id that is not a UUID, a --context that is not valid JSON, a context that is not a JSON object, and a context whose username, accessLevel, targetOrg, taskId, taskType or message is not a string.

v52.18.0 — September 15, 2026

  • A package install that composes partial CustomObject metadata — layout assignments from mutators/layout-assignments.yml, and the search-layouts contribution that augments them — carries the target org's object settings into that partial: the supported feature flags, description, gender, startsWith, each targeted record type's description, and the name field's trackHistory and trackFeedHistory. A CustomObject deployment resets allowInChatterGroups, enableActivities and enableReports and clears description, gender and startsWith when they are omitted, so the composed partial previously reset them on install.
  • That composition stops before deployment when the org's CustomObject metadata is incomplete — a missing label or nameField, an AutoNumber name field with no displayFormat, a value that is not a valid boolean, or an enableBulkApi/enableSharing/enableStreamingApi group that is inconsistent — instead of composing a partial that would reset a property.
  • Each setting is written only when the Metadata API version supports it. The version is the one the install deploys with, falling back to the package's apiVersion and then to the component set's.
  • sfp validate org runs its AI error analysis before it publishes the validation result, so the analysis reaches the published result and its markdown as well as the CI check. It previously ran only while the CI check was being created.
  • sfp validate org cancels the AI error analysis at its timeout — three minutes, unless errorAnalysis.timeout in the AI configuration sets another, in milliseconds — and aborts the agent session rather than leaving the request in flight. A transient failure is retried up to three attempts, after 5 and 10 seconds, within that same deadline.
  • The validation markdown records AI error analysis unavailable: <reason> when the analysis produces no insight, where the reason is no credentials, timed out, unparseable response, attempts exhausted or analysis failed.
  • sfp validate org reads its AI configuration from the validation worktree — config/ai-assist.yaml, then the .yml spelling, then config/ai-architecture.yaml and .yml — rather than from the directory the command was started in. The analysis is skipped when the run failed because no changes were detected in the packages to be built, and runs whenever --opencode-server is set.
  • sfp releasecandidate unbundle removes the file when a conflict has no copy of it on the side --conflict-strategy selects, instead of resolving markers in a file that side deleted.
  • sfp releasecandidate unbundle fails when it cannot resolve the new SHA of a cherry-picked commit. It previously logged a warning and continued, leaving the deployment step lineage incomplete.
  • sfp releasecandidate unbundle-analyze counts only re-applied commits in the kept-commit total it prints and returns. A commit that turned out empty after conflict resolution, and was skipped, is no longer counted.
  • sfp auth login and sfp server auth login serve branded sign-in result pages on the CLI's loopback receiver. The failure page escapes the detail returned by the authorization server and names sfp auth login as the command to run again.
  • sfp publish includes the repository and an ISO 8601 timestamp in the webhook events it triggers on sfp server. The repository is read from SFP_REPOSITORY, GITHUB_REPOSITORY or GITLAB_REPOSITORY, in that order.

v52.17.0 — September 11, 2026

  • sfp publish --pushgittag pushes the tags for all published packages in a single git push, instead of one push per package. A transient failure — a dropped connection, an unresolved host, an HTTP 5xx — is retried three times, after 2, 5 and 15 seconds. An authentication, permission, protected-tag or ruleset rejection is not retried.
  • sfp publish completes when the tag push does not, instead of failing the run. It lists the tags that still need pushing and the git push origin refs/tags/… command that pushes them, with remote URLs and credentials stripped from the reported error, and leaves the --gittaglimit and --gittagage cleanup for that retry.
  • sfp releasecandidate unbundle --source-branch defaults to the branch recorded on the release candidate, falling back to main when the candidate records none. It previously always defaulted to main. An explicit value still takes precedence.
  • sfp releasecandidate unbundle removes its temporary worktree when the run fails as well as when it succeeds, and raises a failure through the command's own error handling — so --json reports it — instead of exiting immediately.
  • sfp releasecandidate unbundle reports how many manual deployment steps were re-anchored onto the rewritten branch and how many were flagged for review. The command fails when the server cannot record that anchor migration, after the branch has been pushed.

v52.16.1 — September 10, 2026

  • sfp server update pauses Hatchet worker assignments before it drains, then waits only for workflows that occupy a worker slot. Queued tasks are no longer waited on; they stay pending and run once the workers return. The drain is checked again after the image pre-pull and the Caddy recreation, and the paused workers are restored when the update finishes or fails.
  • sfp server update aborts before it stops any service when the drain fails or the running-workflow count cannot be read. It previously logged a warning and continued with the update. --force still skips both the pause and the drain, and --drain-timeout still bounds the wait, in seconds, defaulting to 3600.
  • sfp scratch delete completes without error when the Dev Hub holds no active scratch org record for the username. The lookup previously raised No ActiveScratchOrg found for username <username>, which the command reported as a missing org or a permissions failure.

v52.16.0 — September 8, 2026

  • sfp org login --server --default-devhub accepts --repository (alias --repo) to authenticate with the DevHub selected for that project, and fails when the server resolves the DevHub from anywhere else. sfp server org get-default-devhub takes the same flag. Both name where the DevHub came from — the project's default DevHub, a legacy project registration, or the tenant default.
  • sfp scratch login without --devhub-username has the server resolve the DevHub that owns the scratch org, instead of trying the tenant default DevHub and then each registered DevHub in turn.
  • sfp sandbox login without --production-username has the server resolve the production org bound to the sandbox, instead of trying each registered production org in turn. A sandbox registered without a production connection logs in, and the output omits the Production Org line.
  • sfp server pool monitor names the pool it is reconciling when it reads sandbox state from Salesforce, so the state covers that pool's own instances rather than every sandbox under the Dev Hub.
  • sfp scratch delete fails when the Dev Hub rejects the deletion, instead of reporting success. A username with no active scratch org record in the Dev Hub is left alone.
  • --passphrase on the SSH-based server commands — sfp server init, start, stop, status, logs, scale and update — is passed to the SSH connection, so an encrypted --identity-file can be used. The key is read when the flags are parsed and is no longer written into the lifecycle configuration that debug logging serialises.
  • Those same commands report an SFTP error raised while checking for a directory on the remote host, instead of treating the directory as absent.

v52.15.1 — September 7, 2026

  • sfp server update and sfp server init copy the Supabase schema to a remote host through a temporary archive that is extracted and then removed. Removing it now tolerates an archive that is already gone, so a repeated or concurrent run against the same tenant directory no longer fails after the extraction has succeeded.

v52.15.0 — September 4, 2026

  • sfp auth login and sfp server auth login sign in to flxbl cloud when no server URL is given, through the global auth service over OAuth 2.1 with PKCE and a loopback receiver bound to 127.0.0.1. --sfp-server-url no longer defaults to http://localhost:3029.
  • sfp auth login --sfp-server-url reads the server's /sfp/api/config before signing in: a server that reports itself as self-hosted routes the sign-in to the auth service it publishes, and an unreachable URL fails before a browser opens. --global-auth and --no-global-auth force either service and no longer carry a default.
  • sfp auth login prints the sign-in URL before it opens a browser, so a session where no browser opens can still complete the sign-in. On the self-hosted path the browser is redirected to the server's hosted /auth/callback page, which shows an sfp1_ login code to paste into the terminal when it cannot reach the CLI's loopback.
  • sfp install and sfp release group the output of each pre- and post-deployer and of the preDeployment and postDeployment scripts, and keep the component checksum skip pre-fetch lines inside the eligibility group.

v52.14.3 — September 2, 2026

  • sfp analyze --output-format github renders code-analyzer and architecture findings as a Markdown list — severity, rule, location and gate on the first line, the message on the next — instead of an HTML table. --output-format markdown keeps its tables.
  • sfp analyze and sfp project version suggest pass the architecture and version-assist instructions to the AI as its system prompt, rather than prepending them to the pull request content being analysed. The architecture instructions return the empty JSON result the parser reads when there is no architecturally significant change, in place of a plain sentence.

v52.14.2 — September 2, 2026

  • sfp project preflight reports a repository with no sfdx-project.json, or one that cannot be parsed, as a not-configured status with the cause listed under issues. Previously the read error aborted the run.

v52.14.1 — September 2, 2026

  • sfp cascade merge-assist no longer stops responding when the AI agent asks to access a directory outside the working tree. The request is answered instead of left pending.

v52.14.0 — September 1, 2026

  • sfp validate grounds its AI analysis of a failure. Commands it suggests are checked against the CLI's own command set, and browserforce settings are reported as org-UI settings rather than as CLI flags.
  • A package build reports a missing Package2 registration in the Dev Hub as that, instead of as a generic creation failure.
  • Repository and npm-registry calls to sfp server report the server's own error message instead of a generic substitute.

August 2026

v52.12.0 — August 30, 2026

  • sfp analyze runs the version-assist AI linter only when it is asked for. --version-assist runs it, --no-version-assist keeps it off even when the project enables it, and with neither flag it runs only when the server project settings explicitly enable it.
  • A package install that fails on a transport error — a dropped connection, DNS, or TLS failure — names the underlying cause instead of reporting fetch failed.
  • sfp server scale sizes both Hatchet worker pools. --workers sets the general pool and sizes the long-running pool proportionally; --longrunning-workers sets the long-running pool explicitly; --drain-timeout bounds the wait for in-flight work, and --force scales down without draining.

v52.10.2 — August 27, 2026

  • sfp analyze reports a linter that was skipped as skipped, instead of reporting it as a pass.

v52.10.0 — August 26, 2026

  • sfp validate org --waittime sets the metadata deployment wait for each package, in minutes. Defaults to 120.
  • sfp org drift analyze --max-ai-findings skips the AI review when the mechanical candidate count exceeds the threshold. Defaults to 50.
  • sfp apextests resume bounds result fetching, so a large-org run stores its results instead of abandoning them on a timeout.
  • sfp server init creates the admin team, so a newly initialised admin can manage the organisation.

v52.9.3 — August 25, 2026

  • Dependency resolution ignores source package dependencies declared inside the same project.

On this page