--- name: fcode-cli description: Use the Factorial Code CLI (fcode) for local development and cloud sync — the pull → add → run → push flow, the local webhook/forms server, workspace versions and aliases, and the workspace config files (metadata.json, settings.json, variables). Use when running fcode commands, testing a process locally, syncing to the cloud, cloning every App of a development team, inspecting or resolving differences between local and cloud, or configuring a process's webhook, Factorial Action (the `factorial` block — form, UI trigger, agent tool, backend), or version settings. license: MIT metadata: category: factorial-code --- # Factorial Code — CLI The `fcode` CLI develops and tests processes locally and syncs them with Factorial Code Cloud. For the platform model see `fcode-core-concepts`. ## Command flow First time on a machine: install with `pnpm install -g @factorialco/fcode-cli`, then **`fcode clone `** to bring a cloud workspace down into a `/` folder (it also installs these agent skills; skip that with `--skipSkillsSetup`). The "How to build locally" guide on an App's Development tab shows the exact clone command for its dev workspace — copy it from there, the slug is an encoded token, not the App's UUID. To bring down **every** App your development team owns in one layout, use `fcode team:clone` instead (below). When making and testing changes in an already-cloned workspace: 1. **`fcode pull`** *(optional, first)* — if the cloud may have changed, sync down so you work with the latest version. 2. Edit local files (processes, modules, variables, dependencies). 3. **`fcode add`** — **only when you created NEW resources** (new process, module, dependency, or variable). Skip for edits to existing code. 4. **`fcode dependencies:install`** — if you changed `dependencies/package.json` or `dependencies/requirements.txt`. 5. **`fcode run `** — execute the process locally to test. 6. **`fcode push`** — deploy to cloud when ready. Pushing updates the **current** (unversioned) code only: consumers pinned to the `stable` alias — which webhook URLs and form embeds should always be — keep running the released version until the alias moves. Releases (publishing a workspace version and re-pointing `stable`) happen separately, normally from the web UI (see below). ## Gotchas - **Never run `fcode run` before `fcode add`** when the process (or other resource) was *just created* — you'll hit "Local process not found". - **`fcode add` is only for NEW resources.** For edits to existing process/module code or variables, go straight to `fcode push`. - **`--force` (on `push`/`pull`) overwrites the other side.** Both commands fail when local and cloud diverge — `settings:pull` included, which refuses to wipe an unpushed `settings.json`. Run `fcode diff` first to show the user exactly what would be discarded, and only use `--force` with explicit user confirmation. - **Editing `versions` / `aliases` in `settings.json` releases on push**: adding a tag publishes that workspace version, removing one deletes it from the cloud (cascading), re-pointing an alias is a release or rollback. Same rule as `settings:versions:*` / `settings:aliases:*` — **don't touch unless explicitly asked.** - **Never edit inherited resources.** `variables.inherited.env`, `i18n/.inherited.yaml`, and inherited processes/modules are owned by parent workspaces, regenerated on pull, and never pushed (see below). Override a variable by adding the key to `variables.env` (a locale key to `i18n/.yaml`); edit processes and modules in the owning workspace. ## Commands ### `fcode add` Registers **new** local resources with the CLI so they can be run or deployed. Run after creating a new process/module/dependency/variable, before `run`/`push`. Not needed after only editing existing resources. ### `fcode dependencies:install` Installs dependencies into the local workspace. Run after changing `dependencies/package.json` or `dependencies/requirements.txt`. Installs the inherited packages too, so a local run resolves what the cloud does. ### `fcode run --parameters ` Executes a process locally for development/testing. Uses `variables.env` / `variables.local.env` and the given parameters (or the process's `parameters.json` by default). Shows logs, results, and errors. ```sh fcode run my-process --parameters '{"key": "value"}' fcode run my-process --parameters ./params.json fcode run my-process # default parameters.json fcode run my-process --locale pt-BR # resolve fcode.i18n in that locale ``` Prerequisite: run `fcode add` first if the resource was just created. `--locale` resolves `fcode.i18n` against the local `i18n/` files exactly as the cloud does — see `fcode-i18n` (including why a typo in the flag silently resolves every key to itself). ### `fcode http` Starts a local HTTP server (`--port`, default `3000`) that replicates the cloud webhook environment and also serves the workspace's form schemas, so webhook-triggered processes and forms can be exercised without deploying. `--auth-user` / `--auth-password` protect the **whole** local server with basic auth. Per-process webhook auth is separate, and enforced exactly as the cloud does it: the server reads `webhook.authMode` from the process's `metadata.json`, resolves `TEAM` against `webhookAuth` in `settings.json`, and requires the named variable's value in the configured header — `Bearer ` in `Authorization`, the raw value in any other header. Values come from the workspace variables in the precedence every local run uses — `variables.inherited.env`, overridden by `variables.env`, overridden by `variables.local.env` (below). Header lookup is case-insensitive, but a repeated header is rejected rather than joined. A missing header, a malformed bearer value, an undefined variable, a mismatch, or a `TEAM` webhook whose workspace configuration is absent all get a `403`, with the reason printed to the console. Two things to watch locally: - A **secret** variable pulls down as the `********` placeholder, so local auth only accepts `********` until the real value is in `variables.local.env`. - `--auth-user` / `--auth-password` consume the `Authorization` header, so they can't be combined with a webhook expecting its credential there. The server warns about this at startup. ### `fcode pull` Downloads the latest processes, modules, variables, and dependencies from the cloud, overwriting local files to match. Run before starting work if others may have changed cloud resources, or to discard local changes. `--force` only with user confirmation. ### `fcode push` Uploads local changes to the cloud. Run after local changes (run `fcode add` first only if you created new resources); recommended to `fcode run` first. `--force` only with user confirmation. ### `fcode status` Reports what differs between local and cloud without changing either — processes, modules, variables, dependencies, locales, and `settings.json`. Per-resource variants exist too: `processes:status`, `modules:status`, `variables:status`, `i18n:status`, `settings:status`. **Inherited resources the cloud agrees on are hidden**, since there is nothing to pull or push for them; a line reports how many were left out. An inherited resource reappears as soon as it differs — out-of-date, new, removed, conflict, modified, sensitivity-changed — so a parent moving one is never silently swallowed. `--showInherited` lists them all: ```sh fcode status --showInherited # or any per-resource variant above ``` An inherited **sensitive** variable counts as unchanged and is hidden too: its value is never compared, so it could never report as up to date. ### `fcode diff []` Shows **what** differs, where `status` only says **that** something does: a git-style unified diff of every file the workspace is stored as, with the cloud as the old side and the local files as the new one. Per-resource variants take an optional slug: `processes:diff`, `modules:diff`, `variables:diff`, `i18n:diff`, `dependencies:diff`, `settings:diff`. ```sh fcode diff # the whole workspace fcode processes:diff my-process # one process ``` Use it before resolving a `🔥 (conflict)` from `pull` / `push`, so the user sees what each side would lose before choosing. Notes: - **Exits `1` when local and cloud differ**, `0` when in sync — usable as a check. A non-zero exit here is the answer, not a failure to report as an error. - Sensitive variable values are never printed; both sides render as `