Skip to content
Local environment Preproduction — not production data

Changelog

Notable changes to the Factorial Code platform, console, CLI, forms SDK and MCP server, newest first. Each entry is dated by the day it landed on the platform. Changes marked Breaking need action on your side.

Internal infrastructure work (observability, CI, local development) is not listed.

  • fcode team:clone brings down the team’s global workspaces too. The global workspaces a development team owns are checked out under global-workspaces/{slug} alongside the App folders, and fcode team:pull / team:status cover them like any other workspace. A team folder cloned before this picks them up on its next team:pull. See Clone every App of your team.
  • Breaking — the CLI renames the team topic to settings (@factorialco/fcode-cli 3.0.0). fcode team:* managed the settings of the current workspace, a leftover of the platform calling a workspace a team. That name now belongs to the development team, whose commands arrived alongside it.

    BeforeAfter
    fcode team:pull|push|status|difffcode settings:pull|push|status|diff
    fcode team:versions:* / team:aliases:*fcode settings:versions:* / settings:aliases:*
    fcode settings:get|set|remove (CLI preferences)fcode config:get|set|remove
    team.jsonsettings.json

    A workspace holding a legacy team.json keeps working — it is renamed on first access, with no re-clone and no manual step, and already-cloned workspaces still report as up to date. The old command names are gone rather than aliased, because team:pull and team:status now mean something else. See the CLI reference.

  • Breaking — pin an inherited workspace to a version of its parent. Each parent link takes an optional version: pick one of the parent’s workspace versions — a tag, or an alias such as stable — and everything that parent contributes comes from that release until you move the pin. A pinned parent contributes a strict snapshot: only what it published under that tag, with the snapshot’s content. parentTeamSlugs is replaced by parentTeams, a list of {slug, version} entries, in settings.json, the API and the SDK, with no compatibility shim — update anything that writes the old field. See Workspace hierarchy.

  • Dependencies are versioned — a dependency set is publishable under a tag, aliasable, and published as part of a workspace version, and a pinned execution resolves the packages that version pinned instead of the live manifest. Until now a release shipped frozen code and frozen translations against floating packages: editing the dependencies afterwards silently changed what every published version installed. See Versioning dependencies.
  • fcode diff — a git-style unified diff between the workspace and the cloud, with the cloud as the old side, so the patch reads as what a push would apply. Scoped forms take an optional slug: processes:diff, modules:diff, variables:diff, i18n:diff, dependencies:diff, settings:diff. It exits 1 when local and cloud differ and 0 when they are in sync, so CI can use it as a sync check. See Diff local and cloud changes.
  • fcode status hides inherited resources that are in sync with the cloud, behind a new --showInherited flag, so the rows that need attention are not crowded out. Anything actionable still shows, with a one-line count of what was hidden. fcode diff reports drifted inherited resources the same way.
  • fcode team:clone clones every App of a development team in one command, into a consistent layout with the agent skills installed once and shared across every App. Getting a team’s code onto a laptop no longer means one fcode clone per App with slugs looked up by hand. See the CLI reference.
  • One installation lifecycle on the marketplace — a company’s installation is a single stored status (connection_pending, configuration_pending, active) rather than a status plus a separate connected flag, so the next step — the OAuth popup, the install form, or nothing — is unambiguous. Submitting the install form now advances the installation to active, which nothing on the Factorial marketplace path did before.
  • Workspaces are named after their App — the workspace switcher shows My Legacy HR platform Importer, My Legacy HR platform Importer - dev and My Legacy HR platform Importer - company 125339 instead of dev-1fc5hvvo4ubam2puxuz1y83b7. The slug is unchanged; this is the display name.
  • Per-call locale overridefcode.i18n(key, args, { locale }) resolves that one lookup in another locale, so a single execution can speak several languages, such as emailing each employee in their own. It combines with version pinning, and the fallback chain is never worse than without it: requested locale, then the execution’s locale, then the primary. See Overriding the locale per call.
  • Dependency inheritance — a workspace’s effective dependency set is now its parents’ manifests merged with its own, per package name, child wins. A child workspace can run an inherited process without copying the parent’s manifest in. See Dependencies and Workspace hierarchy.
  • Multi-step forms in a single process — a form declares its steps in the schema’s ui:steps node and the process executes once, after the last step, receiving every parameter as a one-page form would. Chaining separate processes with nextProcessId is no longer needed for a purely visual split. See Multi-step forms.
  • Factorial UI trigger buttons — a process can declare that it renders a button at a registered location inside the Factorial product UI, with its own label and icon, configured from the process settings.
  • one:read and one:write OAuth scopes are available in the scope catalog, so Apps can request them when they are created or edited. See OAuth & API token.
  • fcode syncs workspace versions and aliases — the versions and aliases fields in settings.json are now synced state: fcode settings:status reports local changes, fcode settings:push creates the missing versions and re-points aliases, and fcode settings:pull no longer wipes them (the commands were fcode team:* until 28 August). See the CLI reference and Workspace versioning.
  • Factorial OAuth applications are provisioned automatically for every App, for both development and production. Creating a Doorkeeper application by hand and pasting the client id and secret back into the console is no longer part of the setup.
  • Inherited resources are hidden by default in the processes, modules, i18n and variables lists, behind a “Show inherited” switch, and the three lists that lacked it gained name search. The switch is not shown on a workspace with no parents.
  • Breaking — execution messages are markdown (fcode-react-forms 3.0.0, rjsf-f0 2.0.0). A form result message / errorMessage is rendered as GitHub Flavored Markdown; raw HTML is dropped. GFM tables render as an f0 table with sticky headers and Excel/CSV export. schema.<field>.rawHtml.before/after is replaced by schema.<field>.markdown.before/after. Rewrite HTML messages as markdown.
  • keepSuccessView on FcodeForm — an embedder that passes its own onSuccess can keep the default success view (the markdown result message) instead of replacing it. Marketplace form pages now show it.
  • Developer, support and help links on marketplace listings. The vendor is derived from the owning team, and the support and help links are declared on the App’s Marketplace tab.
  • Set the stable release — App members choose which deployed release is the stable one, and the stable alias on the App’s production workspace follows. Customer deploy workspaces resolve it through inheritance. The first deployed release becomes stable automatically.
  • One Install button on the marketplace — Connect and Install are a single action. It redirects through OAuth when there is no connection yet, then provisions the deploy workspace and renders the install form. Uninstalling now revokes the connection and the deploy workspace’s FACTORIAL_TOKEN, so a reinstall never reuses an old credential.
  • Parent order is the inheritance precedence — a team’s parent list is ordered and the first parent wins conflicts, for processes, modules, variables and locales. Reordering parents is a real change: fcode status detects it and fcode push persists it. See Workspace hierarchy.
  • Filter the App list by requested OAuth scopes, marketplace visibility and language, on top of the existing status, team and framework filters.
  • Internationalization — a workspace holds one YAML file per language under i18n/, and process code, module code and form schemas resolve keys through fcode.i18n("key", args). A workspace picks a primary locale used as the fallback, a missing key resolves to itself so a gap never breaks an execution, and locales can be pinned to a version. Locales inherit from parent workspaces key by key rather than file by file. See Internationalization.
  • Cmd+S / Ctrl+S saves on every screen with a save bar. Monaco keeps owning the shortcut inside a code editor.
  • Team variables inherit from parent workspaces — a workspace uses the variables defined in its parents and overrides any of them with its own value, resolved current-workspace-first then parents in order. The old dashboard workaround that copied parent variables into each new workspace — secrets as a placeholder someone filled in by hand — is gone. See Team variables.
  • The web client runs on the f0 design system — every screen renders f0 components, aligning the console with the rest of Factorial.
  • @factorialco/rjsf-f0 supports f0-react 6 alongside 4, so a host on either major can pass rjsfTheme={Theme} against a single f0-react instance. Released as 1.1.0, no component code changed.
  • The active tab lives in the URL on the App detail, App settings and Team detail pages, so a tab can be linked and shared.
  • The forms SDK packages are on npm@factorialco/fcode-react-forms and @factorialco/rjsf-f0 are published to the registry, so consumers install them normally instead of vendoring a tarball. See Installation.
  • Forms render with f0 components — a new standalone @factorialco/rjsf-f0 theme renders real f0 components on f0 surfaces. The hosted forms.js embed, which loads on arbitrary third-party pages, keeps the dependency-free stylesheet theme. See Customization.
  • Reworked App setup checklist and environment tabs — the tabs follow the App lifecycle (Development, Production, Publication), OAuth is tracked as two steps rather than one, and a new informational “Build the App locally” step opens the CLI commands prefilled with the App’s dev workspace slug. See the developer journey.
  • Request a DatoCMS link — App members can ask for their marketplace metadata to be linked to its DatoCMS record instead of only seeing read-only text.
  • Per-company development deployments — an App in development can be installed into a specific demo company and exercised through the marketplace before it is released. A company can hold a dev and a prod deployment of the same App; the dev deploy workspace inherits live dev code with no release pinning.
  • Workspace versioning — creating a workspace version publishes the same tag on every process, module and locale the workspace owns, and workspace aliases such as production manage the per-entity aliases across all of them. Inherited entities are never touched, and per-entity versioning keeps working independently. A partially failed release is safe to retry. See Workspace versioning.
  • Pin a version without a header — webhooks and the four form endpoints accept a version_tag query parameter, which takes precedence over Fcode-Version-Tag, and an embedded form accepts the version as an attribute. Third-party senders that only let you configure a URL can now target a version. See Process versioning.
  • Breaking — workspace-level webhook authentication. A webhook is public, protected by the workspace configuration, or protected by its own header and variable. The header name is configurable, so senders that cannot use Authorization: Bearer — including Factorial’s own webhook sender — can authenticate. Per-process authVariable becomes an authMode plus a {headerName, variableKey} pair. See Webhooks.
  • The founding member of a team is its admin — the requester who creates a development team joins as admin and can invite members and change roles without an operator. Someone approved into a team that already has members still joins as developer. See Roles & permissions.
  • UI/UX pass over the console and the marketplace — searchable workspace pickers in the clone dialog, tighter list columns, and marketplace pages that use the standard console chrome.
  • Breaking — webhooks are protected by a team variable. Basic auth on process webhooks is replaced by a single named team variable: callers send its value as Authorization: Bearer <token>. A missing header, a token mismatch or an undefined variable all return 401. See Webhooks.
  • Forms can require a Factorial user token — a form opts in with authMode = FACTORIAL, after which the form endpoints validate a credential instead of being fully public. Forms that run app code on customer data should opt in.
  • Processes are referenced by slug in generated embed snippets, playground links and the console’s copy-link action. A slug survives a move between workspaces, where a UUID does not. Existing id-based embeds keep working.
  • fcode syncs the form auth modeform.authMode round-trips through processes/<slug>/metadata.json, so a protected form is no longer pulled to disk as a public one, and the mode can be changed from the repository.
  • The App detail page follows the setup journey — tabs reordered, and a collapsible “Set up this App” checklist with per-step state and a progress bar replaces the stacked warnings.
  • Marketplace inside the console — Factorial customers sign in with Factorial OAuth, browse Apps published to production, install them for their company and manage what they installed.
  • Private Apps — an App can be marked private with an allowlist of company ids, and is then only listed and installable by those companies, on both marketplace surfaces.
  • OAuth scopes are optional when creating an App — an App that never calls the Factorial public API no longer has to request a scope, and its setup checklist can reach completion. See OAuth & API token.
  • Global workspaces can be owned by a team — the owning team’s roster gets access, so the workspace appears in the web client’s team selector and can be picked as a parent workspace.
  • Forms show a loading placeholder sized to the real form while the schema loads, instead of a zero-height container that pops into a full form. A form with a preRenderProcess waits seconds rather than milliseconds, so the skeleton matters.
  • Deployments list and end-user actions — a Deployments page listing the team’s deployments, filterable by App and company id. The deployment detail page shows copyable links to share with the customer’s end users: the OAuth authorization link and each form-enabled process, grouped by app role.
  • UNINSTALL app role — a process can be marked as the App’s uninstall action, alongside INSTALL, SETTINGS and USER_FACING_FORM.
  • Form file uploads expire after 1 hour instead of a week. They are short-lived intake artifacts. See Storage.
  • fcode clone installs the agent skills non-interactively, targeting Claude Code reliably in a fresh workspace. See Skills.
  • Requesting access is separate from creating an App — the public form creates an access request, and approval provisions only the development team and the requester’s account. A team member then creates Apps themselves, provisioned immediately with no approval step.
  • Square logo per App, uploaded from the Edit App dialog and served publicly for marketplace branding.
  • OAuth scopes are editable after the App is created, not only in the creation wizard.
  • Developers see the New deployment action on the App detail page; it was gated to operators in the UI even though the API always allowed it.
  • fcode round-trips the app roleappRole is read, stored in processes/<slug>/metadata.json and written back, so a role set in the console survives a pull and can be changed from the repository.
  • App roles on process form settings — a process declares whether its form is the App’s INSTALL form, its SETTINGS form, a USER_FACING_FORM, or NONE. The role travels through the release and inheritance chain with the process.
  • Marketplace metadata and screenshots editor in the console: markdown description, tagline, categories and screenshots per App.
  • MCP clients can register themselves — the MCP server returns the resource_metadata URL on 401s and serves resource-specific protected-resource metadata, so OAuth discovery and dynamic client registration work in clients like VS Code without a manual client-id flow. See the MCP server quickstart.
  • fcode clone --autoSkillsSetup installs the agent skills with defaults and no prompts, for scripted clones. Also available as a persistent setting.
  • Enter submits dialog forms in the console, where it previously did nothing.
  • Copy the dev FACTORIAL_TOKEN from the App’s OAuth tab, so it can be used when cloning the workspace to a local workstation. See API credentials.
  • preRenderProcess on a form schema — the named process runs while the form is served and its returned variables are merged into the form’s variables, so a single form can compute its own render-time data. The throwaway first step whose only job was to fetch data is no longer needed. See Getting started with forms.
  • App settings are open to App members — managing OAuth credentials, starting the dev OAuth flow and editing the App name and description no longer need an operator. App lifecycle actions (suspend, archive, delete) stay operator-only.