fcode-cli

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Factorial Code — CLI

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
.
fcode
CLI可用于本地开发和测试流程,并将其与Factorial Code Cloud同步。平台模型请参考
fcode-core-concepts

Command flow

命令工作流

When making and testing changes:
  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 <process-slug>
    — 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).
进行变更和测试时:
  1. fcode pull
    (可选,第一步)——如果云端可能有变更,先同步最新版本到本地,确保基于最新内容工作。
  2. 编辑本地文件(流程、模块、变量、依赖项)。
  3. fcode add
    ——仅当你创建了新资源(新流程、模块、依赖项或变量)时执行。编辑现有代码时无需执行此命令。
  4. fcode dependencies:install
    ——如果修改了
    dependencies/package.json
    dependencies/requirements.txt
    ,执行此命令。
  5. fcode run <process-slug>
    ——在本地执行流程进行测试。
  6. fcode push
    ——准备就绪后部署到云端。
推送操作仅更新当前(未版本化)代码:固定到
stable
别名的消费者——webhook URL和表单嵌入应始终使用该别名——会继续运行已发布版本,直到别名指向变更。发布操作(发布工作区版本并重新指向
stable
)需单独进行,通常通过Web UI完成(见下文)。

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; only use
    --force
    with explicit user confirmation.
  • Never edit
    variables.inherited.env
    .
    It holds the parent workspaces' variables, is regenerated on pull, and
    fcode push
    skips it with a warning. Overriding an inherited value means adding the key to
    variables.env
    .
  • 当流程(或其他资源)刚创建时,切勿在
    fcode add
    之前运行
    fcode run
    ——否则会出现“Local process not found”错误。
  • fcode add
    仅适用于新资源
    。对于现有流程/模块代码或变量的编辑,直接执行
    fcode push
    即可。
  • --force
    参数(用于
    push
    /
    pull
    )会覆盖另一方内容
    。当本地和云端内容不一致时,两个命令都会失败;仅在获得用户明确确认后使用
    --force
  • 切勿编辑
    variables.inherited.env
    。该文件存储父工作区的变量,会在pull操作时重新生成,
    fcode push
    会跳过该文件并发出警告。要覆盖继承的值,需将键添加到
    variables.env
    中。

Commands

命令说明

fcode add

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.
向CLI注册新的本地资源,以便运行或部署。创建新流程/模块/依赖项/变量后,在执行
run
/
push
之前运行此命令。仅编辑现有资源时无需执行。

fcode dependencies:install

fcode dependencies:install

Installs dependencies into the local workspace. Run after changing
dependencies/package.json
or
dependencies/requirements.txt
.
将依赖项安装到本地工作区。修改
dependencies/package.json
dependencies/requirements.txt
后执行此命令。

fcode run <process-slug> --parameters <filepath | json>

fcode run <process-slug> --parameters <filepath | json>

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).
在本地执行流程以进行开发/测试。使用
variables.env
/
variables.local.env
和指定的参数(默认使用流程的
parameters.json
)。显示日志、结果和错误信息。
sh
fcode run my-process --parameters '{"key": "value"}'
fcode run my-process --parameters ./params.json
fcode run my-process                                  # 默认使用parameters.json
fcode run my-process --locale pt-BR                   # 以该区域解析fcode.i18n
前提条件:如果资源刚创建,需先运行
fcode add
--locale
参数会像云端一样,根据本地
i18n/
文件解析
fcode.i18n
——请参考
fcode-i18n
(包括为何该参数中的拼写错误会静默地将每个键解析为自身)。

fcode http

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
team.json
, and requires the named variable's value in the configured header —
Bearer <token>
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.
启动本地HTTP服务器(
--port
参数指定端口,默认3000),该服务器复制云端webhook环境,同时提供工作区的表单模式,无需部署即可测试webhook触发的流程和表单。
--auth-user
/
--auth-password
参数使用基础认证保护整个本地服务器。每个流程的webhook认证是独立的,并严格按照云端规则执行:服务器从流程的
metadata.json
读取
webhook.authMode
,从
team.json
webhookAuth
解析
TEAM
,并要求在配置的头中包含指定变量的值——
Authorization
头中的
Bearer <token>
,或其他头中的原始值。值来自工作区变量,优先级与本地运行一致——
variables.inherited.env
,被
variables.env
覆盖,再被
variables.local.env
覆盖(见下文)。头查找不区分大小写,但重复的头会被拒绝而非合并。缺少头、格式错误的bearer值、未定义的变量、值不匹配,或
TEAM
webhook对应的工作区配置缺失,都会返回
403
,原因会打印到控制台。
本地运行时需注意两点:
  • 机密变量会以
    ********
    占位符的形式拉取,因此本地认证仅接受
    ********
    ,直到真实值被添加到
    variables.local.env
    中。
  • --auth-user
    /
    --auth-password
    会占用
    Authorization
    头,因此无法与期望在该头中获取凭证的webhook结合使用。服务器在启动时会对此发出警告。

fcode pull

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.
从云端下载最新的流程、模块、变量和依赖项,覆盖本地文件以保持一致。如果其他人可能修改了云端资源,或要丢弃本地变更,在开始工作前运行此命令。仅在获得用户确认后使用
--force

fcode push

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 add
);建议先执行
fcode run
测试。仅在获得用户确认后使用
--force

fcode team:pull
/
team:push
/
team:status

fcode team:pull
/
team:push
/
team:status

Sync the workspace-level settings in
team.json
on their own:
team:pull
writes the cloud settings into the file,
team:push
applies the file, and
team:status
reports whether they changed locally, in the cloud, or both. Plain
fcode pull
/
fcode push
include them too, running them last so a referenced error-handler process slug resolves against processes that already exist.
单独同步工作区根目录
team.json
中的工作区级设置:
team:pull
将云端设置写入文件,
team:push
应用文件中的设置,
team:status
报告本地、云端或两者的设置是否有变更。普通的
fcode pull
/
fcode push
也会包含这些设置,但会最后执行,确保引用的错误处理流程slug能解析到已存在的流程。

fcode team:versions:*
/
fcode team:aliases:*

fcode team:versions:*
/
fcode team:aliases:*

Workspace versioning publishes a version of the whole workspace: every process and module the team owns gets a version with the same tag, and bare module imports are pinned to it inside the published snapshots (model in
fcode-core-concepts
). Releases normally happen from the web UI (team settings → Versions tab) — these commands are the scriptable equivalent. Don't create versions or move
stable
unless explicitly asked.
sh
fcode team:versions:create v1.0.0 --comment "First stable release"
fcode team:versions:list
fcode team:versions:delete v1.0.0     # cascades; asks confirmation unless --force

fcode team:aliases:set stable v1.0.0  # create or re-point; rollback = older tag
fcode team:aliases:list
fcode team:aliases:delete stable
  • team:versions:create
    skips entities already carrying the exact tag and reports a per-entity summary (created / skipped / failed — the version's manifest), then pulls so the
    versions/<tag>/
    folders and
    team.json
    refresh locally. Re-running the same tag after a partial failure only publishes what is still missing.
  • team:versions:delete
    cascades
    : every owned process/module version with the tag is deleted, together with the aliases, executions, and schedules referencing them.
  • team:aliases:set
    upserts
    — it creates the alias or re-points an existing one on every owned entity that has the target tag published (entities without it are skipped and reported). Re-pointing
    stable
    at an older tag is the rollback: every consumer pinned to
    stable
    switches in one operation.
工作区版本管理会发布整个工作区的版本:团队拥有的每个流程和模块都会获得相同标签的版本,裸模块导入会固定到已发布快照中的该版本(模型请参考
fcode-core-concepts
)。发布操作通常通过Web UI完成(团队设置→Versions标签)——这些命令是可脚本化的等效操作。除非明确要求,否则不要创建版本或移动
stable
别名。
sh
fcode team:versions:create v1.0.0 --comment "First stable release"
fcode team:versions:list
fcode team:versions:delete v1.0.0     # 级联删除;除非使用--force,否则会要求确认

fcode team:aliases:set stable v1.0.0  # 创建或重新指向;回滚即指向旧标签
fcode team:aliases:list
fcode team:aliases:delete stable
  • **
    team:versions:create
    **会跳过已携带完全相同标签的实体,并报告每个实体的摘要(已创建/已跳过/失败——版本清单),然后执行pull操作,刷新本地的
    versions/<tag>/
    文件夹和
    team.json
    。部分失败后重新运行相同标签,仅发布仍缺失的内容。
  • team:versions:delete
    会级联删除
    :所有带有该标签的自有流程/模块版本,以及引用它们的别名、执行记录和调度都会被删除。
  • team:aliases:set
    会更新或插入
    ——它会在所有已发布目标标签的自有实体上创建别名或重新指向现有别名(没有该标签的实体会被跳过并报告)。将
    stable
    重新指向旧标签就是回滚操作:所有固定到
    stable
    的消费者会一次性切换版本。

fcode i18n:*

fcode i18n:*

i18n:pull
/
i18n:push
/
i18n:status
/
i18n:add <locale>
/
i18n:remove <locale>
/
i18n:reset
sync the workspace's translation files —
i18n/<locale>.yaml
, plus the read-only, gitignored
i18n/<locale>.inherited.yaml
that
pull
writes. Aggregate
fcode pull
/
push
/
status
include locales already. File format, inheritance model, and the internationalization workflow in
fcode-i18n
.
i18n:pull
/
i18n:push
/
i18n:status
/
i18n:add <locale>
/
i18n:remove <locale>
/
i18n:reset
用于同步工作区的翻译文件——
i18n/<locale>.yaml
,以及pull操作生成的只读、git忽略的
i18n/<locale>.inherited.yaml
。聚合的
fcode pull
/
push
/
status
也会包含区域设置。文件格式、继承模型和国际化工作流请参考
fcode-i18n

Process metadata —
metadata.json

流程元数据 —
metadata.json

Each process folder holds
processes/<slug>/metadata.json
— the source of truth for the process's name, description, tags, triggers, and settings. It round-trips with
push
/
pull
: edit the file and
fcode push
to change these settings in the cloud, no dashboard needed. Changes show as 🔺 modified in
fcode status
.
FieldTypeMeaning
name
stringDisplay name (defaults to the slug)
description
string, optionalProcess description
tags
string[]Tags (defaults to
[]
)
webhook
object, optionalWebhook trigger:
enabled
(boolean) turns the process's webhook endpoint on;
authMode
(
NONE
|
TEAM
|
CUSTOM
) says how callers authenticate — public, inheriting the workspace
webhookAuth
from
team.json
, or its own;
auth
(
{ headerName?, variableKey }
, only with
CUSTOM
) names the header and the team variable holding the expected token
form
object, optionalForm settings:
enabled
(boolean) is the Forms flag (see
fcode-forms
);
authMode
(
FACTORIAL
|
NONE
) restricts who may open the form;
appRole
marks the process's role in a marketplace app:
INSTALL
,
SETTINGS
,
USER_FACING_FORM
, or
UNINSTALL
json
{
  "name": "Order sync",
  "description": "Syncs Shopify orders into Factorial",
  "tags": ["integration", "shopify"],
  "webhook": {
    "enabled": true,
    "authMode": "CUSTOM",
    "auth": { "variableKey": "SHOPIFY_WEBHOOK_TOKEN" }
  },
  "form": { "enabled": false }
}
A webhook that inherits the workspace configuration carries
"webhook": { "enabled": true, "authMode": "TEAM" }
, and a public one only
"webhook": { "enabled": true }
.
json
{
  "name": "Connect your account",
  "tags": ["setup"],
  "form": { "enabled": true, "authMode": "FACTORIAL", "appRole": "INSTALL" }
}
Notes:
  • webhook.auth.variableKey
    stores only the variable name, never a token
    — so the file is safe to commit. The variable doesn't have to exist yet; until it does, every call to the webhook is rejected with
    403
    . Both plain and secret variables work.
  • authMode: TEAM
    inherits
    webhookAuth
    from
    team.json
    .
    When that configuration is missing, the webhook rejects every call — it never reads as public. Through MCP this matters: an agent can set
    authMode: TEAM
    but there is no team-settings tool, so the configuration has to exist already (set it in
    team.json
    and
    fcode team:push
    ).
  • webhook.auth.headerName
    defaults to
    Authorization
    , whose value must be
    Bearer <token>
    ; any other header carries the raw variable value. Valid names are RFC 7230 token characters, at most 64 of them, and
    Cookie
    ,
    Host
    and the
    Fcode-
    prefix are rejected. Prefer the default: a bespoke header loses the redaction proxies and log pipelines give
    Authorization
    . Use one only when the sender can't set
    Authorization
    — Factorial's own webhook sender, which puts its token in
    x-factorial-wh-challenge
    , is the case in point.
  • form.authMode
    ,
    form.appRole
    and
    webhook.authMode
    are omitted when they are
    NONE
    , as is
    webhook.auth.headerName
    when it is
    Authorization
    , so a plain public form carries only
    "form": { "enabled": true }
    . To lift protection from a protected form or webhook, write
    "authMode": "NONE"
    explicitly — omitting the field leaves the stored mode untouched, and sending
    auth
    without
    authMode: CUSTOM
    is rejected.
  • Omit
    form.appRole
    unless the process belongs to a marketplace app.
  • If
    metadata.json
    is missing,
    fcode add
    scaffolds
    { "name": "<slug>", "tags": [] }
    ; invalid JSON falls back to those defaults with a warning.
每个流程文件夹中都包含
processes/<slug>/metadata.json
——这是流程名称、描述、标签、触发器和设置的权威来源。它会随
push
/
pull
双向同步:编辑该文件并执行
fcode push
即可在云端更改这些设置,无需使用仪表板。变更会在
fcode status
中显示为🔺 modified。
字段类型含义
name
string显示名称(默认值为slug)
description
string, optional流程描述
tags
string[]标签(默认值为
[]
webhook
object, optionalWebhook触发器:
enabled
(boolean)开启流程的webhook端点;
authMode
NONE
|
TEAM
|
CUSTOM
)指定调用者的认证方式——公开、继承工作区
team.json
中的
webhookAuth
,或自定义;
auth
{ headerName?, variableKey }
,仅在
CUSTOM
模式下可用)指定头名称和存储预期令牌的团队变量
form
object, optional表单设置:
enabled
(boolean)为表单开关(请参考
fcode-forms
);
authMode
FACTORIAL
|
NONE
)限制可打开表单的用户;
appRole
标记流程在市场应用中的角色:
INSTALL
SETTINGS
USER_FACING_FORM
UNINSTALL
json
{
  "name": "Order sync",
  "description": "Syncs Shopify orders into Factorial",
  "tags": ["integration", "shopify"],
  "webhook": {
    "enabled": true,
    "authMode": "CUSTOM",
    "auth": { "variableKey": "SHOPIFY_WEBHOOK_TOKEN" }
  },
  "form": { "enabled": false }
}
继承工作区配置的webhook会携带
"webhook": { "enabled": true, "authMode": "TEAM" }
,公开webhook仅携带
"webhook": { "enabled": true }
json
{
  "name": "Connect your account",
  "tags": ["setup"],
  "form": { "enabled": true, "authMode": "FACTORIAL", "appRole": "INSTALL" }
}
注意事项:
  • webhook.auth.variableKey
    仅存储变量名称,从不存储令牌
    ——因此该文件可安全提交。变量无需预先存在;在变量创建之前,所有webhook调用都会被拒绝并返回
    403
    。普通变量和机密变量均适用。
  • authMode: TEAM
    继承
    team.json
    中的
    webhookAuth
    。当该配置缺失时,webhook会拒绝所有调用——绝不会视为公开。通过MCP时这一点很重要:代理可设置
    authMode: TEAM
    ,但没有团队设置工具,因此配置必须预先存在(在
    team.json
    中设置并执行
    fcode team:push
    )。
  • webhook.auth.headerName
    默认为
    Authorization
    ,其值必须为
    Bearer <token>
    ;任何其他头都携带变量的原始值。有效名称为RFC 7230令牌字符,最多64个,
    Cookie
    Host
    Fcode-
    前缀会被拒绝。建议使用默认值:自定义头会失去代理和日志管道对
    Authorization
    头的脱敏处理。仅当发送方无法设置
    Authorization
    时才使用自定义头——Factorial自身的webhook发送方会将令牌放入
    x-factorial-wh-challenge
    ,就是这种情况。
  • form.authMode
    form.appRole
    webhook.authMode
    NONE
    时会被省略
    webhook.auth.headerName
    Authorization
    时也会被省略,因此普通公开表单仅携带
    "form": { "enabled": true }
    。要取消受保护表单或webhook的保护,需显式写入
    "authMode": "NONE"
    ——省略该字段会保留存储的模式,发送
    auth
    但未设置
    authMode: CUSTOM
    会被拒绝。
  • 除非流程属于市场应用,否则省略
    form.appRole
  • 如果
    metadata.json
    缺失,
    fcode add
    会生成脚手架
    { "name": "<slug>", "tags": [] }
    ;无效JSON会回退到这些默认值并发出警告。

Calling a webhook — pin the version in the URL

调用webhook — 在URL中固定版本

The webhook endpoint is
https://code.factorialhr.com/platform/api/<team-slug>/webhooks/<process-slug>
. Always pin the version with the
version_tag
query parameter, pointing at the
stable
alias — subscription systems rarely let you set request headers:
sh
curl -X POST "https://code.factorialhr.com/platform/api/<team-slug>/webhooks/<process-slug>?version_tag=stable"
  • version_tag
    takes a version tag (
    v1.0.0
    ) or an alias. Use
    stable
    : it always exists, and releases/rollbacks then happen by moving the alias — the external system is never touched. It is equivalent to the
    Fcode-Version-Tag
    header and takes precedence over it.
    version_tag
    ,
    async
    and
    locale
    are reserved names, stripped before the parameters reach the process (
    locale
    selects the execution's language — see
    fcode-i18n
    ).
  • An unknown or malformed version does not fail the call. The process runs its current version and the platform only logs a server-side warning — a typo runs the current version silently. When a run behaves unexpectedly, check the execution's version.
Webhook端点为
https://code.factorialhr.com/platform/api/<team-slug>/webhooks/<process-slug>
。始终使用
version_tag
查询参数固定版本,指向
stable
别名——订阅系统通常不允许设置请求头:
sh
curl -X POST "https://code.factorialhr.com/platform/api/<team-slug>/webhooks/<process-slug>?version_tag=stable"
  • version_tag
    接受版本标签(
    v1.0.0
    )或别名。使用
    stable
    :它始终存在,发布/回滚操作只需移动别名——无需修改外部系统。它等效于
    Fcode-Version-Tag
    头,且优先级更高。
    version_tag
    async
    locale
    是保留名称,在参数到达流程前会被剥离(
    locale
    选择执行的语言——请参考
    fcode-i18n
    )。
  • 未知或格式错误的版本不会导致调用失败。流程会运行其当前版本,平台仅在服务器端记录警告——拼写错误会静默运行当前版本。当运行行为异常时,请检查执行的版本。

Team settings —
team.json

团队设置 —
team.json

A singleton file at the workspace root holding team-level settings. Synced by
fcode team:pull
/
team:push
/
team:status
, and included in plain
fcode push
/
pull
(pushed last, so a referenced error-handler process exists first).
FieldTypeMeaning
parentTeamSlugs
string[]Teams this workspace inherits processes, modules and variables from (direct parents only, max 5)
zoneId
string, optionalTeam timezone (e.g. for schedules)
errorHandlerConfig
object, optional
{ "processSlug": "<slug>", "tag": null }
— process invoked when an execution errors;
tag
pins it to a version tag or alias (
null
= current version)
webhookAuth
object, optional
{ headerName?, variableKey }
— the configuration every
authMode: TEAM
webhook inherits
primaryLocale
string, optionalThe workspace's main language: the locale used when a caller names none, and the key-level fallback for untranslated keys (see
fcode-i18n
)
versions
array, pull-onlyWorkspace versions:
{ tag, comment, createdAt }
aliases
array, pull-onlyWorkspace aliases:
{ name, tag }
json
{
  "parentTeamSlugs": ["base-app"],
  "zoneId": "Europe/Madrid",
  "errorHandlerConfig": { "processSlug": "error-handler", "tag": null },
  "webhookAuth": {
    "headerName": "x-factorial-wh-challenge",
    "variableKey": "FACTORIAL_CHALLENGE_TOKEN"
  },
  "versions": [
    { "tag": "v1.0.0", "comment": "First stable release", "createdAt": "2026-08-01T10:00:00" }
  ],
  "aliases": [{ "name": "stable", "tag": "v1.0.0" }]
}
The error handler is referenced by slug (not id) so
team.json
is portable across teams; the CLI resolves it to the cloud id on push.
versions
and
aliases
are pull-only:
team:pull
writes them for visibility and git history, they are excluded from the content hash, and
team:push
strips them — editing them locally does nothing. All writes go through the
team:versions:*
/
team:aliases:*
commands or the web UI.
webhookAuth
is one shared configuration for the whole workspace, so a token used by several webhooks is named — and rotated — in one place. Two things about it:
  • It is per-workspace and not inherited through
    parentTeamSlugs
    .
    Auth is resolved against the workspace addressed in the webhook URL, not the one that owns the code, so an app inheriting a webhook process from a base app still needs its own
    webhookAuth
    entry.
  • Removing the object and pushing clears the cloud configuration, which makes every webhook inheriting it reject all calls.
工作区根目录的单例文件,存储团队级设置。通过
fcode team:pull
/
team:push
/
team:status
同步,普通的
fcode push
/
pull
也会包含这些设置(最后推送,确保引用的错误处理流程已存在)。
字段类型含义
parentTeamSlugs
string[]该工作区继承流程、模块和变量的团队(仅直接父团队,最多5个)
zoneId
string, optional团队时区(例如用于调度)
errorHandlerConfig
object, optional
{ "processSlug": "<slug>", "tag": null }
——执行出错时调用的流程;
tag
固定到版本标签或别名(
null
表示当前版本)
webhookAuth
object, optional
{ headerName?, variableKey }
——所有
authMode: TEAM
的webhook继承的配置
primaryLocale
string, optional工作区的主要语言:当调用者未指定区域时使用的区域,以及未翻译键的键级回退(请参考
fcode-i18n
versions
array, pull-only工作区版本:
{ tag, comment, createdAt }
aliases
array, pull-only工作区别名:
{ name, tag }
json
{
  "parentTeamSlugs": ["base-app"],
  "zoneId": "Europe/Madrid",
  "errorHandlerConfig": { "processSlug": "error-handler", "tag": null },
  "webhookAuth": {
    "headerName": "x-factorial-wh-challenge",
    "variableKey": "FACTORIAL_CHALLENGE_TOKEN"
  },
  "versions": [
    { "tag": "v1.0.0", "comment": "First stable release", "createdAt": "2026-08-01T10:00:00" }
  ],
  "aliases": [{ "name": "stable", "tag": "v1.0.0" }]
}
错误处理流程通过slug(而非ID)引用,因此
team.json
可在团队间移植;CLI会在推送时将其解析为云端ID。
versions
aliases
仅pull的字段:
team:pull
会写入这些字段以提供可见性和git历史,它们不包含在内容哈希中,
team:push
会剥离这些字段——本地编辑不会产生任何效果。所有写入操作需通过
team:versions:*
/
team:aliases:*
命令或Web UI完成。
webhookAuth
是整个工作区的共享配置,因此多个webhook使用的令牌只需在一处命名和轮换。关于它的两点注意事项:
  • 它是每个工作区独有的,不会通过
    parentTeamSlugs
    继承
    。认证是针对webhook URL中指定的工作区解析的,而非拥有代码的工作区,因此从基础应用继承webhook流程的应用仍需自己的
    webhookAuth
    条目。
  • 删除该对象并推送会清除云端配置,这会使所有继承该配置的webhook拒绝所有调用。

The three variables files

三个变量文件

Team variables live in three
.env
files at the workspace root:
FileHoldsSynced
variables.env
The variables this workspace ownsCommitted; pushed and pulled
variables.inherited.env
The variables inherited from parent workspaces (
parentTeamSlugs
)
Pull-only; gitignored (the CLI adds the entry)
variables.local.env
Local-only overridesNever pushed, never pulled
Resolution order for a local run (highest wins), matching what the cloud does:
variables.local.env
variables.env
variables.inherited.env
.
Precedence is decided by which file declares a key, not by its value — so blanking a key in
variables.env
overrides the inherited variable with an empty string rather than falling through to the parent.
团队变量存储在工作区根目录的三个
.env
文件中:
文件存储内容同步方式
variables.env
该工作区拥有的变量可提交;会被推送和拉取
variables.inherited.env
父工作区
parentTeamSlugs
)继承的变量
仅可拉取;已加入git忽略(CLI会添加该条目)
variables.local.env
仅本地生效的覆盖变量从不推送,从不拉取
本地运行的解析顺序(优先级从高到低),与云端一致:
variables.local.env
variables.env
variables.inherited.env
优先级由哪个文件声明键决定,而非值——因此在
variables.env
中将键设为空字符串会覆盖继承的变量,而非回退到父工作区的值。

Overriding an inherited variable

覆盖继承的变量

Adding the key to
variables.env
is the override.
From that point the CLI treats it as this workspace's own variable:
fcode status
shows it as new,
fcode push
creates it here, and
fcode variables:add
offers it.
  • Don't edit
    variables.inherited.env
    — it is regenerated on every pull, and
    fcode push
    skips inherited variables with a warning. Editing one only warns.
  • Don't copy a parent's variables into a child workspace to "make them available" — they already resolve. Only add a key when this workspace genuinely needs a different value. (Workspaces provisioned before inheritance existed may still hold such copies, which now shadow the parent — including untouched
    ********
    placeholders shadowing a secret that would otherwise resolve. Flag those to the user rather than deleting them.)
  • Deleting your override (removing the key from
    variables.env
    and pushing) brings the parent's value back.
fcode variables:status
grows an inherited column showing the source workspace (
🔗 <slug>
) when any variable is inherited; the column is hidden otherwise. Model and web-UI behaviour in
fcode-core-concepts
; the runtime
fcode.variables
behaviour in
fcode-javascript
/
fcode-python
.
The file names are settings (
variablesFileName
,
inheritedVariablesFileName
,
localVariablesFileName
) — assume the defaults above unless the workspace says otherwise.
将键添加到
variables.env
即完成覆盖
。此后CLI会将其视为该工作区的自有变量:
fcode status
会显示为新增,
fcode push
会在云端创建它,
fcode variables:add
会提供该变量。
  • 切勿编辑
    variables.inherited.env
    ——它会在每次pull操作时重新生成,
    fcode push
    会跳过继承变量并发出警告。编辑该文件只会收到警告。
  • 切勿将父工作区的变量复制到子工作区以“使其可用”——它们已被解析。仅当该工作区确实需要不同值时才添加键。(继承功能出现之前配置的工作区可能仍有此类副本,现在会覆盖父工作区的值——包括未修改的
    ********
    占位符会覆盖原本可解析的机密变量。需向用户标记这些情况,而非直接删除。)
  • 删除覆盖项(从
    variables.env
    中移除键并推送)会恢复父工作区的值。
fcode variables:status
会增加一个inherited列,当有变量被继承时显示源工作区(
🔗 <slug>
);否则该列会隐藏。模型和Web UI行为请参考
fcode-core-concepts
;运行时
fcode.variables
的行为请参考
fcode-javascript
/
fcode-python
文件名是可配置的(
variablesFileName
inheritedVariablesFileName
localVariablesFileName
)——除非工作区另有说明,否则使用上述默认名称。

Variable sensitivity —
variables.meta.json

变量敏感性 —
variables.meta.json

A workspace-root file mapping each variable to its sensitivity flag:
json
{
  "ACME_API_KEY": { "isSensitive": true },
  "ACME_BASE_URL": { "isSensitive": false }
}
  • Create a sensitive variable with
    fcode variables:add --sensitive
    (then set its value and push); the flag lands here.
  • Variables created at runtime with
    fcode.variables.set
    are sensitive by default — pass
    sensitive: false
    (JS) /
    sensitive=False
    (Python) for plain config. See
    fcode-javascript
    /
    fcode-python
    .
  • Sensitive values never leave the cloud:
    pull
    writes the placeholder
    ********
    into
    variables.env
    — and into
    variables.inherited.env
    for an inherited secret. Don't replace the placeholder in either file — put the real value in
    variables.local.env
    for local runs. Remotely, an inherited secret's real value is available to executions (see
    fcode-core-concepts
    ); only the local copy is masked.
  • isSensitive
    is immutable
    once pushed. Editing it in
    variables.meta.json
    is rejected on push (🚫 in
    fcode status
    ) — revert to match remote.
工作区根目录的文件,将每个变量映射到其敏感性标志:
json
{
  "ACME_API_KEY": { "isSensitive": true },
  "ACME_BASE_URL": { "isSensitive": false }
}
  • 使用
    fcode variables:add --sensitive
    创建机密变量(然后设置其值并推送);该标志会存储在此文件中。
  • 通过
    fcode.variables.set
    在运行时创建的变量默认是机密的——对于普通配置,需传递
    sensitive: false
    (JS)/
    sensitive=False
    (Python)。请参考
    fcode-javascript
    /
    fcode-python
  • 机密值永远不会离开云端
    pull
    操作会在
    variables.env
    中写入占位符
    ********
    ——对于继承的机密变量,会在
    variables.inherited.env
    中写入该占位符。切勿替换任一文件中的占位符——将真实值放入
    variables.local.env
    用于本地运行。在远程环境中,继承的机密变量的真实值可用于执行(请参考
    fcode-core-concepts
    );仅本地副本会被掩码。
  • isSensitive
    一旦推送就不可变
    。在
    variables.meta.json
    中编辑它会在推送时被拒绝(
    fcode status
    中显示🚫)——需回退以匹配远程版本。

Getting secret values for local runs

获取本地运行的机密值

When a local run (
fcode run
, a discovery script) needs a real secret value that isn't in
variables.local.env
yet, ask the user to provide it. If they prefer not to share the value with the agent, ask them to add the
KEY=value
line to
variables.local.env
themselves — local runs pick it up without the value ever appearing in the conversation.
  • variables.local.env
    values are never pushed.
    Remind the user to also create those secret variables manually in the remote demo environment —
    fcode push
    won't carry the values.
  • FACTORIAL_TOKEN
    : needed locally only — the remote environment populates it automatically, so don't create it there. To obtain it, the user completes the OAuth flow in the Factorial Code app details page, then copies the generated token with the copy dropdown option in the OAuth Dev app, and puts it in
    variables.local.env
    (or shares it, per their preference).
  • Once obtained, never echo secret values back in output or logs.
当本地运行(
fcode run
、发现脚本)需要真实的机密值且该值尚未在
variables.local.env
中时,请让用户提供该值。如果用户不愿与代理共享该值,请让他们自行将
KEY=value
行添加到
variables.local.env
中——本地运行会自动读取该值,且值不会出现在对话中。
  • variables.local.env
    中的值永远不会被推送
    。提醒用户还需在远程演示环境中手动创建这些机密变量——
    fcode push
    不会携带这些值。
  • FACTORIAL_TOKEN
    :仅本地运行需要——远程环境会自动填充该值,因此无需在远程创建。要获取该令牌,用户需在Factorial Code应用详情页完成OAuth流程,然后在OAuth Dev应用中使用复制下拉选项复制生成的令牌,并将其放入
    variables.local.env
    中(或根据偏好共享)。
  • 获取后,切勿在输出或日志中回显机密值。

Examples

示例

Development cycle (new process):
sh
fcode add
fcode dependencies:install            # if dependencies changed
fcode run shopify-order-sync --parameters '{"dateFrom":"2024-01-01","dateTo":"2024-01-31"}'
fcode push                            # no need to re-run `add` if nothing new was created
Deploy an existing, tested process:
sh
fcode push                            # `add` not needed — process already registered
开发周期(新流程):
sh
fcode add
fcode dependencies:install            # 如果依赖项有变更
fcode run shopify-order-sync --parameters '{"dateFrom":"2024-01-01","dateTo":"2024-01-31"}'
fcode push                            # 如果未创建新资源,无需重新运行`add`
部署已测试的现有流程:
sh
fcode push                            # 无需`add`——流程已注册