create-railcode-app

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Create Railcode App

创建Railcode应用

Update First

先更新

Before answering a Railcode question or running a
railcode
command, update the Railcode skills and CLI, then verify npm's published version:
bash
npx skills add Railcode-HQ/railcode-skills
npm install -g railcode@latest
railcode --version
npm view railcode version
If the skill changes, re-read this file from the top. If npm is unreachable, say so and do not claim the guidance is current. This version was written against CLI 0.1.36 — the CLI source in the
railcode-multi-tenant
repo.
The source is ahead of npm. npm's published
latest
was 0.1.35 when this was written, so
npm install -g railcode@latest
does not yet give you 0.1.36. Everything marked 0.1.36+ below —
railcode ci github
,
railcode token
, and
RAILCODE_ORG_UUID
— is absent from the published binary, and a CI job on 0.1.35 fails with "No organization on file" however valid its token. Check
railcode --version
against
npm view railcode version
before relying on those; if you are on 0.1.35, say so rather than assuming the commands exist.
The app editor tier and empty-string flag values (
--editors ""
) require 0.1.35; on an older server the CLI's new access fields are ignored rather than failing.
Since 0.1.28 the CLI self-updates within its major version — but only on an interactive terminal, and agent-driven sessions are non-interactive, so keep running the explicit
npm install -g railcode@latest
above rather than assuming you're on the latest.
在回答Railcode相关问题或执行
railcode
命令前,请先更新Railcode技能包和CLI,然后验证npm上的已发布版本:
bash
npx skills add Railcode-HQ/railcode-skills
npm install -g railcode@latest
railcode --version
npm view railcode version
如果技能包有更新,请从头重新阅读本文档。如果无法访问npm,请直接说明,不要声称当前指导内容是最新的。本文档是基于CLI 0.1.36编写的——CLI源码位于
railcode-multi-tenant
仓库。
源码版本领先于npm版本。 编写本文档时,npm上发布的
latest
版本为0.1.35,因此执行
npm install -g railcode@latest
暂时无法获取0.1.36版本。以下标记为0.1.36+的功能——
railcode ci github
railcode token
RAILCODE_ORG_UUID
——在已发布的二进制文件中不存在,使用0.1.35版本执行CI任务时会提示*"No organization on file"*,无论令牌是否有效。在依赖这些功能前,请对比
railcode --version
npm view railcode version
的结果;如果使用的是0.1.35版本,请直接说明,不要假设这些命令已存在。
应用的editor层级和空字符串标志值(
--editors ""
)需要0.1.35版本支持;在旧版服务器上,CLI的新访问字段会被忽略,不会导致执行失败。
从0.1.28版本开始,CLI会在主版本范围内自动更新——但仅在交互式终端中生效,而Agent驱动的会话是非交互式的,因此请始终执行显式的
npm install -g railcode@latest
命令,不要默认认为已处于最新版本。

Map The Request To Railcode

将需求映射到Railcode功能

Use this table before choosing an architecture. If the request names an external product or data source, always check data connections/saved queries, service connectors, and personal connectors before deciding what is available; the detailed discovery commands are in step 1.
Hard file boundary: the app may upload, store, list, download, and display files with
files
, but any AI that must read, understand, extract, summarize, transform, or generate a file must be a managed agent with
app_files
and its sandbox. Never pass file contents, file URLs, or file-derived payloads to
llm.generate()
/
llm.stream()
as a substitute, and never use the in-page LLM to produce a file artifact. Use the app as the upload/results UI and delegate the file work through
agents.invoke()
/
agents.start()
.
What the user asks forUse this Railcode feature
"Show company metrics/orders/customers from our database"Saved query via
query()
(default); data connection + direct
data().runSQL()
only when explicitly requested
"Let each user connect their Gmail, Slack, or another personal account"Personal connector via
personalConnections
; declare only the needed
personal_connectors
tools
"Connect my account to a product Railcode does not bundle"Custom MCP personal connector by remote HTTPS URL, then call its
custom_<slug>
toolkit
"Use our team's shared Stripe, CRM, or other SaaS account"Org service connector via
connector().fetch()
; an admin owns the shared credential
"Store app settings, drafts, approvals, or lightweight records"App KV via
db.shared
,
db.user
, or
db.role()
according to ownership
"Upload, store, download, or display files without AI processing"Scoped app
files
"Read, extract, summarize, transform, or generate a file with AI"Managed agent with
app_files
+ sandbox; never
llm.generate()
/
llm.stream()
"Edit this Word document / DOCX and preserve it as a file"Managed agent + companion app: the app stores/manages source and output files; the agent loads the DOCX with
app_files
, edits it in its sandbox, and publishes the result with
app_data_write
"Create or revise a PowerPoint / PPTX deck"Managed agent + companion app: the app manages templates, inputs, and generated decks; the agent creates/edits the PPTX in its sandbox and publishes it back to the app
"Create a PDF report, form, or document"Managed agent + companion app: the app manages inputs and downloadable outputs; the agent generates and verifies the PDF in its sandbox, then publishes it back to the app
"Analyze this Excel / XLSX workbook"Managed agent + companion app: the app stores the workbook and results; the agent loads it with
app_files
, parses/analyzes it in its sandbox, and publishes durable results through
app_data_write
"Summarize or classify data while the user is watching"In-page
llm.generate()
/
llm.stream()
with narrowly wired tools
"Run in the background, on a schedule, from Slack, or after the tab closes"Managed agent invoked with
agents
, often with this app as its companion UI
"Send a system-owned transactional email"Platform
email.send()
; use a Gmail personal connector instead when mail must come from each user's own account
"Call an arbitrary website/API"First look for a service or personal connector; otherwise offer admin connector setup or a custom MCP personal connector—apps cannot fetch the open web directly
在选择架构前,请使用下表进行匹配。如果用户需求中提到了外部产品或数据源,在决定可用功能前,请务必检查数据连接/已保存查询、服务连接器以及个人连接器;详细的发现命令见步骤1。
文件处理边界:应用可以通过
files
进行文件上传、存储、列出、下载和展示,但任何需要读取、理解、提取、总结、转换或生成文件的AI操作必须由具备
app_files
权限和沙箱环境的托管Agent完成。切勿将文件内容、文件URL或文件衍生的负载传递给
llm.generate()
/
llm.stream()
作为替代方案,也不要使用页面内LLM生成文件产物。请将应用作为上传/结果展示UI,通过
agents.invoke()
/
agents.start()
委托文件处理工作。
用户需求对应的Railcode功能
"展示我们数据库中的公司指标/订单/客户数据"默认使用已保存查询,通过
query()
调用;仅当用户明确要求时,才使用数据连接+直接
data().runSQL()
"让每个用户连接自己的Gmail、Slack或其他个人账户"通过
personalConnections
使用个人连接器;仅声明所需的
personal_connectors
工具
"将我的账户连接到Railcode未内置的产品"通过远程HTTPS URL创建自定义MCP个人连接器,然后调用其
custom_<slug>
工具集
"使用我们团队共享的Stripe、CRM或其他SaaS账户"通过
connector().fetch()
使用组织级服务连接器;共享凭证由管理员维护
"存储应用设置、草稿、审批记录或轻量级数据"根据所有权,使用
db.shared
db.user
db.role()
实现的应用KV存储
"上传、存储、下载或展示文件,无需AI处理"带作用域的应用
files
功能
"使用AI读取、提取、总结、转换或生成文件"具备
app_files
权限和沙箱环境的托管Agent;切勿使用
llm.generate()
/
llm.stream()
"编辑此Word文档/DOCX并保留为文件格式"托管Agent + 配套应用:应用负责存储/管理源文件和输出文件;Agent通过
app_files
加载DOCX,在沙箱中编辑,然后通过
app_data_write
发布结果
"创建或修改PowerPoint/PPTX演示文稿"托管Agent + 配套应用:应用负责管理模板、输入内容和生成的演示文稿;Agent在沙箱中创建/编辑PPTX,然后将其发布回应用
"创建PDF报告、表单或文档"托管Agent + 配套应用:应用负责管理输入内容和可下载输出文件;Agent在沙箱中生成并验证PDF,然后将其发布回应用
"分析此Excel/XLSX工作簿"托管Agent + 配套应用:应用负责存储工作簿和结果;Agent通过
app_files
加载工作簿,在沙箱中解析/分析,然后通过
app_data_write
发布持久化结果
"在用户操作时实时总结或分类数据"使用绑定了窄范围工具的页面内
llm.generate()
/
llm.stream()
"在后台运行、按计划运行、从Slack触发或在标签页关闭后运行"通过
agents
调用托管Agent,通常将此应用作为其配套UI
"发送系统所属的事务性邮件"使用平台
email.send()
;当邮件需要从每个用户自己的账户发送时,请改用Gmail个人连接器
"调用任意网站/API"首先查找服务连接器或个人连接器;否则建议管理员设置连接器,或使用自定义MCP个人连接器——应用无法直接访问公开网络

Start From An Example

从示例开始

Railcode ships worked, deployable examples at https://github.com/Railcode-HQ/railcode-examples. Read them to learn a pattern; copy one when it covers much of what the user is asking for.
ExampleWhat it isShowcases
apps/kanban
A kanban board with drag-and-drop columns, a list view, and a command palette.The plain static app: SDK globals, KV storage, Zustand state — no LLM or agents.
apps/chat
A chat interface over your connected data sources (Postgres text-to-SQL, PostHog HogQL).Per-user scoped storage, streaming answers, auditable inline tool calls, file uploads.
apps/crm
A full CRM — companies, contacts, pipeline, activity, automations — with an Ask AI agent that can read and change anything a person could.
llm.stream({ tools })
agent loops, human approval gating on writes, per-tab URL routing, managed agents deployed alongside an app.
The repo's
agents/
directory holds examples that pair an app with a managed agent — reach for those through
$create-railcode-agent
when the work needs one.
Ask, don't assume. When the request substantially overlaps an example, put the choice in the step 1 question batch, naming the example in the user's own terms:
"Railcode provides an example CRM that covers a lot of these points. Should I use that as a starting point, or build from scratch?"
Ask once, alongside the other scoping questions. Never copy an example unprompted, and don't raise the question when nothing matches.
示例说明展示功能
apps/kanban
具备拖拽列、列表视图和命令面板的看板应用纯静态应用:SDK全局变量、KV存储、Zustand状态管理——无LLM或Agent
apps/chat
基于已连接数据源的聊天界面(Postgres文本转SQL、PostHog HogQL)按用户划分的作用域存储、流式回答、可审计的内嵌工具调用、文件上传
apps/crm
完整的CRM应用——包含公司、联系人、销售管道、活动、自动化功能——具备可读写所有数据的Ask AI Agent
llm.stream({ tools })
Agent循环、写入操作的人工审批 gate、按标签页的URL路由、与应用一同部署的托管Agent
仓库的
agents/
目录包含了应用与托管Agent配对的示例——当工作需要Agent时,可以通过
$create-railcode-agent
使用这些示例。
询问用户,不要假设。 当用户需求与某个示例高度重叠时,请在步骤1的问题集中提出选择,用用户能理解的术语提及该示例:
"Railcode提供了一个示例CRM应用,覆盖了您提到的大部分需求。是否以此为起点进行开发,还是从零开始构建?"
请与其他范围界定问题一同一次性提出。切勿未经提示直接复制示例,当没有匹配的示例时也无需提及此问题。

Copying an example

复制示例

Copy only the one directory, as plain files — never
git clone
the repo into the user's project, add it as a submodule, or leave a
.git
behind:
bash
mkdir -p my-crm
curl -fsSL https://github.com/Railcode-HQ/railcode-examples/archive/refs/heads/main.tar.gz \
  | tar -xz --strip-components=3 -C my-crm railcode-examples-main/apps/crm
--strip-components=3
drops
railcode-examples-main/apps/<example>/
, so the example's files land directly in
my-crm/
. Swap the trailing path for any row above (e.g.
railcode-examples-main/apps/chat
). To study one file without copying anything, fetch it raw from
https://raw.githubusercontent.com/Railcode-HQ/railcode-examples/main/<path>
.
A copied example already contains
railcode.json
— it replaces
railcode init
, so don't scaffold over it. Make it the user's app before writing feature code:
  • railcode.json
    — set
    app
    to the new name (lowercase, digits, dashes).
  • package.json
    — rename
    name
    , then
    npm install
    (versions are exact pins with a lockfile).
  • manifest.yaml
    — delete every authority this app doesn't actually use (
    llm
    ,
    agents
    ,
    personal_connectors
    , …). A copied manifest carries the example's authority, not the narrowest set for this app. Re-validate with
    railcode manifest validate
    .
  • agents/*/agent.yaml
    , when present — rename each agent, update the app slug in its
    app_data
    /
    app_files
    /
    app_data_write
    , and update the names in
    manifest.yaml
    's
    agents:
    list and in every
    agents.invoke
    /
    agents.start
    call, so the copy doesn't collide with an agent that already exists in the org.
  • README.md
    , when the example ships one — retitle or replace; it describes the example.
  • Delete the views, stores, and components for features the user didn't ask for.
If the download fails, say so and build from scratch — don't reconstruct an example from memory.
仅复制单个目录中的文件——切勿将仓库
git clone
到用户项目中、添加为子模块或留下
.git
目录:
bash
mkdir -p my-crm
curl -fsSL https://github.com/Railcode-HQ/railcode-examples/archive/refs/heads/main.tar.gz \
  | tar -xz --strip-components=3 -C my-crm railcode-examples-main/apps/crm
--strip-components=3
参数会移除
railcode-examples-main/apps/<example>/
路径,使示例文件直接存入
my-crm/
。请将末尾路径替换为上述任意示例(例如
railcode-examples-main/apps/chat
)。如需查看单个文件而不复制内容,可以通过
https://raw.githubusercontent.com/Railcode-HQ/railcode-examples/main/<path>
获取原始文件。
复制的示例已包含
railcode.json
——它替代了
railcode init
命令,因此无需在其上重新搭建项目。在编写功能代码前,请先将其修改为用户的应用:
  • railcode.json
    ——将
    app
    设置为新名称(小写字母、数字、连字符)。
  • package.json
    ——重命名
    name
    字段,然后执行
    npm install
    (版本为精确固定值,带有锁文件)。
  • manifest.yaml
    ——删除此应用实际不需要的所有权限(
    llm
    agents
    personal_connectors
    等)。复制的清单包含示例应用的权限,而非此应用所需的最小权限集。请使用
    railcode manifest validate
    重新验证。
  • agents/*/agent.yaml
    (如果存在)——重命名每个Agent,更新其
    app_data
    /
    app_files
    /
    app_data_write
    中的应用slug,并更新
    manifest.yaml
    agents:
    列表以及所有
    agents.invoke
    /
    agents.start
    调用中的名称,避免与组织中已存在的Agent冲突。
  • README.md
    (如果示例包含)——重新命名或替换;原README描述的是示例应用。
  • 删除用户未要求的视图、存储和组件。
如果下载失败,请直接说明并从零开始构建——不要凭记忆重构示例。

Build Process (follow in order)

构建流程(按顺序执行)

When building or substantially changing an app, work through these steps in order. Don't start writing app code until steps 1–2 are done.
在构建或大幅修改应用时,请按以下步骤顺序执行。在完成步骤1-2前,不要开始编写应用代码。

1. Ask before building

1. 构建前询问用户

First, ask the user a few short questions to scope the app — all in one batch, as early as possible. This is the moment the user is still present; questions dribbled out mid-build risk landing after they've stepped away. Ask only what changes the design or architecture, then pick sensible defaults for the rest and state them.
Phrase every question for a non-technical user who knows nothing of Railcode internals: ask about intent, and let the answers determine the primitives without naming them. "Should each user get their own private storage, or does everyone work on the same data?" — not "db.shared or db.user?". "Is this data already in a company database someone maintains?" — not "saved query or direct SQL?". The bullets below are what you need to learn from the answers, not the words to use.
Before asking anything, check the request against Limitations below. If it needs something Railcode can't do (a scraper, a public site, a webhook receiver, …), say so plainly first and propose the nearest supported shape — don't build a broken approximation. Cover at least:
External source discovery is mandatory. Whenever the user asks for an app that reads, writes, syncs, searches, or acts on data from a named product or system ("X"), do not assume that a new integration or direct API call is needed. Before settling the architecture, inspect all three Railcode integration planes available to the signed-in user:
bash
railcode db list                       # database/data-source connections
railcode query list                    # admin-published saved queries over those sources
railcode connector list                # org service connectors
railcode personal-connectors list      # per-user bundled and custom toolkits + connection status
If a likely service or personal connector exists, inspect its actual surface before designing around it (
railcode connector docs <name>
or
railcode personal-connectors tools <toolkit>
). Never invent connector names, endpoints, tool slugs, or schemas. If you cannot authenticate or reach the Railcode instance, ask the user what is configured and present the discovery commands; do not treat an empty or unavailable local result as proof that X is unsupported.
If nothing suitable is available, explain the gap and offer the relevant next choices instead of silently dropping the integration: have an admin connect the underlying database and publish a saved query; enable or create an org service connector for a shared credential/API; connect a bundled personal toolkit; or connect X's remote MCP server by URL as a custom personal connector (HTTPS; auth can be none, bearer token, or OAuth). Custom MCP personal connectors work for apps as
custom_<slug>
toolkits. If X has neither an accessible API/database nor a remote MCP server, say that Railcode cannot connect to it directly and ask which supported source the user wants to use. Make the options user-facing (who owns the account, whether access is shared, and any admin setup required), then let the user's choice determine the manifest authority.
  • What & who — what should the app do, and who uses it? (drives access policy and whether data is per-user or shared)
  • Data — what does it store or read? Per-user records or shared across the app's users? Any external database (Postgres/BigQuery/Turso) must be accessed through an admin-published saved query invoked with
    query('name', params)
    unless the user explicitly tells you to use direct/ad-hoc SQL. If the user asks for direct SQL, use
    data('name').runSQL()
    or a dialect-pinned
    postgres
    /
    bigquery
    /
    turso
    namespace with bound params. Any third-party SaaS API to reach via a
    connector('name').fetch()
    service connector? Any
    llm
    use? If AI is involved, also establish its shape: does it read, generate, or otherwise process files, need to write/run code, get triggered outside the app (Slack, schedule), or run unattended? Any yes → a managed agent, never the in-page LLM — see In-Page LLM vs Managed Agents below.
  • Starting point — when an example in Start From An Example covers much of the request, ask whether to build on it: "Railcode provides an example CRM that covers a lot of these points. Should I use that as a starting point, or build from scratch?" (drives step 3)
  • Design"Should I use the default Railcode design system, or do you have a specific design direction?" (drives step 2)
  • Browser testing"Should I test my changes in a browser before calling it done?" (drives step 4)
首先,向用户提出几个简短问题以界定应用范围——所有问题一次性集中提出,越早越好。此时用户仍在场;如果在构建过程中零散提出问题,可能会在用户离开后才得到回复。仅询问会影响设计或架构的问题,其余部分选择合理默认值并告知用户。
请用不了解Railcode内部机制的非技术用户能理解的措辞提问:询问用户的意图,根据回答选择合适的功能,不要提及技术术语。例如,问"每个用户应该拥有自己的私有存储,还是所有人共享同一数据?"——而非"使用db.shared还是db.user?";问"这些数据是否已存储在公司维护的数据库中?"——而非"使用已保存查询还是直接SQL?"。以下要点是需要从回答中获取的信息,而非提问的措辞。
在提问前,请先对照下文的限制条件检查用户需求。如果需求涉及Railcode无法实现的功能(如爬虫、公开站点、Webhook接收器等),请直接说明并提出最接近的支持方案——不要构建无法正常工作的近似版本。至少需要覆盖以下内容:
必须排查外部数据源。 每当用户要求开发读取、写入、同步、搜索或操作指定产品/系统("X")数据的应用时,不要假设需要新的集成或直接API调用。在确定架构前,请检查登录用户可用的所有三个Railcode集成层面:
bash
railcode db list                       # 数据库/数据源连接
railcode query list                    # 管理员发布的基于这些数据源的已保存查询
railcode connector list                # 组织级服务连接器
railcode personal-connectors list      # 按用户划分的内置和自定义工具集 + 连接状态
如果存在匹配的服务连接器或个人连接器,请在围绕其设计前先检查其实际功能(
railcode connector docs <name>
railcode personal-connectors tools <toolkit>
)。切勿自行发明连接器名称、端点、工具slug或 schema。如果无法验证身份或访问Railcode实例,请询问用户已配置的内容并提供发现命令;不要将本地空结果或无法访问的结果视为X不被支持的证据。
如果没有合适的连接器可用,请说明差距并提供相关的后续选择,而非默默放弃集成:让管理员连接底层数据库并发布已保存查询;启用或创建用于共享凭证/API的组织级服务连接器;连接内置个人工具集;或通过URL将X的远程MCP服务器作为自定义个人连接器连接(HTTPS;认证方式可以是无认证、Bearer令牌或OAuth)。自定义MCP个人连接器可作为
custom_<slug>
工具集在应用中使用。如果X既无可用的API/数据库,也无远程MCP服务器,请说明Railcode无法直接连接到它,并询问用户希望使用哪个支持的数据源。请提供用户易懂的选项(谁拥有账户、是否共享访问、是否需要管理员设置),然后根据用户的选择确定清单权限。
  • 用途与用户——应用应该实现什么功能,谁会使用它?(决定访问策略以及数据是按用户私有还是共享)
  • 数据——应用存储或读取什么数据?是按用户划分的私有记录,还是应用用户共享的数据?任何外部数据库(Postgres/BigQuery/Turso)必须通过管理员发布的已保存查询,使用
    query('name', params)
    调用,除非用户明确要求使用直接/临时SQL。如果用户要求使用直接SQL,请使用
    data('name').runSQL()
    或指定方言的
    postgres
    /
    bigquery
    /
    turso
    命名空间,并绑定参数。是否需要通过
    connector('name').fetch()
    服务连接器访问第三方SaaS API?是否需要使用
    llm
    ?如果涉及AI,还需确定其形态:是否需要读取、生成或以其他方式处理文件,是否需要编写/运行代码,是否需要在应用外部触发(Slack、计划任务),或是否需要无人值守运行?只要有一个答案为是,就需要使用托管Agent,而非页面内LLM——请查看下文的页面内LLM vs 托管Agent(云端)
  • 起点选择——当从示例开始部分的某个示例覆盖了用户需求的大部分内容时,请询问用户是否以此为起点:"Railcode提供了一个示例CRM应用,覆盖了您提到的大部分需求。是否以此为起点进行开发,还是从零开始构建?"(决定步骤3)
  • 设计方向——"是否使用默认的Railcode设计系统,还是有特定的设计方向?"(决定步骤2)
  • 浏览器测试——"是否需要在浏览器中测试修改内容后再交付?"(决定步骤4)

2. Fetch the design system (if the user wants it)

2. 获取设计系统(如果用户需要)

If the user chose the Railcode design system, pull it before writing any UI:
bash
railcode login                                       # once, if not already logged in
railcode design-system
railcode design-system
prints your org's configured design-system guidance (markdown) to stdout. Use it as the active design direction. The command needs a logged-in CLI and a reachable Railcode server. If the user wants a custom direction instead, or it returns empty (no admin has configured one for the org), or there is no server to log in to, skip it and use the fallback in the Visual Direction section.
如果用户选择使用Railcode设计系统,请在编写任何UI代码前先获取它:
bash
railcode login                                       # 如果尚未登录,执行一次
railcode design-system
railcode design-system
命令会将你的组织配置的设计系统指南(markdown格式)输出到标准输出。请以此作为当前的设计方向。该命令需要已登录的CLI和可访问的Railcode服务器。如果用户需要自定义设计方向,或命令返回空内容(组织管理员未配置设计系统),或无法登录服务器,请跳过此步骤并使用视觉方向部分的 fallback 方案。

3. Build the app

3. 构建应用

If the user chose an example in step 1, copy that one directory and adapt it first — see Start From An Example. Otherwise scaffold with
railcode init
. Either way, develop locally — see the Core Workflow and Local Development sections — following the Implementation Rules.
Always write or update the app's
manifest.yaml
beside
railcode.json
. Use
run_as: user
for pass-through apps with no privileged app authority, and
run_as: app
only when the app needs ratified saved-query, connector, LLM, email, managed-agent invocation, personal-connector tool-calling, or explicitly requested direct-SQL authority. Validate it with
railcode manifest validate
before deploy.
如果用户在步骤1中选择了某个示例,请先复制该目录并进行适配——请查看从示例开始部分。否则,请使用
railcode init
搭建项目。无论哪种方式,请在本地开发——请查看核心工作流本地开发部分——遵循实现规则
请始终在
railcode.json
旁编写或更新应用的
manifest.yaml
。对于无特权应用权限的直通式应用,使用
run_as: user
;仅当应用需要已批准的已保存查询、连接器、LLM、邮件、托管Agent调用、个人连接器工具调用或用户明确要求的直接SQL权限时,才使用
run_as: app
。在部署前,请使用
railcode manifest validate
验证清单。

4. Test before calling it done

4. 测试后再交付

Run the checks in the Validation section: always the app build, plus a browser pass if the user asked for browser testing in step 1. Fix what you find before declaring the work done.
执行验证部分的检查:始终执行应用构建,如果用户在步骤1中要求浏览器测试,还需进行浏览器测试。在宣布工作完成前,请修复发现的问题。

5. Deploy (when the user wants it live)

5. 部署(当用户需要上线时)

Publish with
railcode deploy
— see the Deployment section. To deploy on every push instead, run
railcode ci github
in the project (CLI 0.1.36+): it mints an app-scoped deploy token, sets it as the repo secret via
gh
, and writes the workflow. Never put a personal token in CI — see Deploy From CI.
使用
railcode deploy
发布应用——请查看部署部分。如果希望在每次推送时自动部署,请在项目中执行
railcode ci github
(CLI 0.1.36+):它会生成应用作用域的部署令牌,通过
gh
设置为仓库密钥,并写入工作流。切勿将个人令牌放入CI——请查看从CI部署

Core Workflow

核心工作流

A normal app-builder loop is:
bash
railcode init my-app          # scaffolds a standalone ./my-app/ directory
cd my-app
npm install                   # only for the react template (the static template has no deps)
railcode dev                  # local server with an emulated /_api
railcode deploy               # build (if configured) + upload to your org
The CLI is the npm package
railcode
(
npm install -g railcode@latest
).
The CLI detects the app's package manager from
packageManager
or a lockfile and otherwise uses
npm
. Examples use
npm
; substitute the app's declared manager. The npm build command is
npm run build
.
Use lowercase app names with digits and dashes only (a DNS label:
^[a-z0-9][a-z0-9-]{0,62}$
).
railcode init <app> [dir]
scaffolds a single self-contained app directory —
./<app>/
by default, or an existing directory you name (
railcode init my-app .
scaffolds into the current dir; non-empty is fine, but an existing
railcode.json
is refused without
--force
). There is no
apps/
/
app-bundles/
workspace split. The directory is the source of truth; the build output (
dist/
for the react template, or the directory itself for the no-build static template) is what
railcode deploy
uploads.
常规的应用构建循环如下:
bash
railcode init my-app          # 搭建独立的./my-app/目录
cd my-app
npm install                   # 仅适用于react模板(静态模板无依赖)
railcode dev                  # 带有模拟/_api的本地服务器
railcode deploy               # 构建(如果已配置)并上传到你的组织
CLI是npm包
railcode
npm install -g railcode@latest
)。
CLI会从
packageManager
字段或锁文件检测应用的包管理器,否则默认使用
npm
。示例中使用
npm
;请替换为应用声明的包管理器。npm的构建命令是
npm run build
应用名称请仅使用小写字母、数字和连字符(符合DNS标签规则:
^[a-z0-9][a-z0-9-]{0,62}$
)。
railcode init <app> [dir]
命令会搭建一个独立的应用目录——默认是
./<app>/
,也可以指定现有目录(
railcode init my-app .
会将项目搭建到当前目录;目录非空也可以,但如果已有
railcode.json
,需要添加
--force
参数才会覆盖)。没有
apps/
/
app-bundles/
工作区拆分。目录是唯一的数据源;构建输出(react模板为
dist/
,无构建静态模板为目录本身)是
railcode deploy
上传的内容。

Decide What To Load

决定加载哪些参考文档

Load only the reference needed for the task:
  • CLI workflow: exact app-building commands (login/init/dev/deploy/design-system, app-facing data/connector/LLM calls, and access) plus local dev/deploy behavior.
  • Platform magic: how same-origin auth,
    /_api/sdk.js
    , app/org identity, access policies, KV/files, SQL, service connectors, LLM, and email work.
  • App patterns: implementation patterns for React/Vite apps, using the SDK globals, data modeling, SQL, connectors, LLM, and frontend expectations.
  • Deployment:
    railcode deploy
    , app access, and post-deploy verification.
For full working apps — a kanban board, a data chat, a CRM with an in-page agent loop — read or copy from
railcode-examples
; see Start From An Example above.
仅加载任务所需的参考文档:
  • CLI工作流:精确的应用构建命令(登录/初始化/开发/部署/设计系统、应用端的数据/连接器/LLM调用、访问控制)以及本地开发/部署行为。
  • 平台魔法:同源认证、
    /_api/sdk.js
    、应用/组织身份、访问策略、KV/文件、SQL、服务连接器、LLM和邮件的工作原理。
  • 应用模式:React/Vite应用的实现模式,包括SDK全局变量的使用、数据建模、SQL、连接器、LLM和前端预期。
  • 部署
    railcode deploy
    、应用访问控制和部署后验证。
如需完整的成品应用——看板、数据聊天、带有页面内Agent循环的CRM——请阅读或复制
railcode-examples
中的内容;请查看上文的从示例开始部分。

Implementation Rules

实现规则

Build a static browser app. Do not add app-specific backend services, credentials, auth code, or hardcoded Railcode URLs unless the user explicitly asks for platform work. Load
/_api/sdk.js
in
index.html
and call its same-origin globals directly; do not import a Railcode client package or create a custom SDK bootstrap.
Give every top-level section its own path (
/companies
,
/people
) and put the open record in the path too (
/companies/acme
) — never keep navigation in an in-memory
view
variable. Deep links, hard refresh, and back/forward must work, since these apps get linked in Slack and tickets. Railcode serving falls back to the app's root
index.html
, so client-side routes resolve with no config — see App patterns.
Use the narrowest surface that fits:
NeedSDK surface
Identity, app members, roles, design guidance
me()
,
appUsers()
,
roles()
,
designSystem()
Shared, private, or role-owned records
db.shared
,
db.user
,
db.role(uuid)
Passive file upload, storage, download, or display
files.shared
,
files.user
,
files.role(uuid)
Database reads
query()
/
savedQueries()
by default; direct SQL only when explicitly requested
Shared third-party account
connector()
/
serviceConnectors()
Viewer's own third-party account
personalConnections
; this includes remote custom MCP toolkits
Short, watched, text/data AI
llm.generate()
/
llm.stream()
with narrowly wired tools
File AI, code execution, or durable/background AI
agents.invoke()
/
agents.start()
and a managed agent
System-owned transactional mail
email.send()
Tools passed to the in-page LLM add no authority; they expose only what their
run
handlers call. Never wire file content, file URLs, file-derived payloads, or file generation into an in-page tool. Delegate all AI file work to a managed agent with
app_files
and a sandbox.
See App patterns for code, Platform magic for auth and scoping semantics, and CLI workflow for manifest authority and exact commands.
构建静态浏览器应用。除非用户明确要求平台相关工作,否则不要添加应用特定的后端服务、凭证、认证代码或硬编码的Railcode URL。在
index.html
中加载
/_api/sdk.js
并直接调用其同源全局变量;不要导入Railcode客户端包或创建自定义SDK引导程序。
为每个顶级部分设置独立路径(
/companies
/people
),并将打开的记录也放入路径中(
/companies/acme
)——切勿将导航存储在内存
view
变量中。深度链接、硬刷新和前进/后退功能必须正常工作,因为这些应用会在Slack和工单中被链接。Railcode服务会回退到应用的根
index.html
,因此客户端路由无需配置——请查看应用模式
使用最贴合需求的最小功能面:
需求SDK功能面
身份、应用成员、角色、设计指南
me()
appUsers()
roles()
designSystem()
共享、私有或角色所有的记录
db.shared
db.user
db.role(uuid)
被动文件上传、存储、下载或展示
files.shared
files.user
files.role(uuid)
数据库读取默认使用
query()
/
savedQueries()
;仅当用户明确要求时才使用直接SQL
共享第三方账户
connector()
/
serviceConnectors()
查看者自己的第三方账户
personalConnections
;包括远程自定义MCP工具集
短时长、用户可见的文本/数据AI处理使用绑定了窄范围工具的
llm.generate()
/
llm.stream()
文件AI处理、代码执行或持久化/后台AI处理
agents.invoke()
/
agents.start()
和托管Agent
系统所属的事务性邮件
email.send()
传递给页面内LLM的工具不会增加权限;它们仅暴露其
run
处理程序调用的内容。切勿将文件内容、文件URL、文件衍生负载或文件生成功能绑定到页面内工具。所有AI文件处理工作必须委托给具备
app_files
权限和沙箱环境的托管Agent。
代码示例请查看应用模式,认证和作用域语义请查看平台魔法,清单权限和精确命令请查看CLI工作流

In-Page LLM vs Managed Agents (Cloud)

页面内LLM vs 托管Agent(云端)

The in-page LLM (
llm.generate
/
llm.stream
, with or without
tools
) runs in the viewer's tab with the app's SDK authority and dies with the tab — bounded to 8 planning turns / 120s by default. A managed agent (
$create-railcode-agent
, invoked from apps via
agents.invoke
/
agents.start
) runs server-side under its own ratified manifest, with a code sandbox and durable, auditable runs. The boundary is capability, not sophistication — a multi-step saved-query analytics assistant is fine in the page; "summarize this PDF" is not. Pick the first matching row:
The AI feature…Use
Summarizes / classifies / analyzes data the app already reads — user watching, done in secondsIn-page LLM
Reads, understands, extracts, summarizes, transforms, or generates any fileManaged agent (
app_files
+ sandbox); never the in-page LLM
Writes and runs codeManaged agent (sandbox)
Is triggered outside the app (Slack, cron, API)Managed agent
Runs unattended, must survive tab close, or needs retriesManaged agent
Has effects that must not depend on who's viewing (shared writes, send as the system)Managed agent
Needs a run history someone will audit or debugManaged agent
The planes compose: keep the chat shell in the page and delegate heavy steps by calling
agents.invoke
/
agents.start
from a tool's
run
— see the delegation pattern in App patterns. The inverse also holds: a managed agent often ships with a companion app that manages the files/records it relies on, renders its results, and gives it a one-click test trigger — see
$create-railcode-agent
.
页面内LLM
llm.generate
/
llm.stream
,带或不带
tools
)在查看者的标签页中运行,使用应用的SDK权限,标签页关闭后即停止——默认限制为8个规划步骤/120秒。托管Agent
$create-railcode-agent
,通过应用中的
agents.invoke
/
agents.start
调用)在服务器端运行,拥有自己的已批准清单,具备代码沙箱环境和持久化、可审计的运行记录。两者的边界是能力,而非复杂度——多步骤的已保存查询分析助手可以在页面内运行;但“总结此PDF”则不行。请选择第一个匹配的选项:
AI功能特性…使用方案
总结/分类/分析应用已读取的数据——用户可见,几秒内完成页面内LLM
读取、理解、提取、总结、转换或生成任何文件托管Agent
app_files
+ 沙箱环境);切勿使用页面内LLM
编写并运行代码托管Agent(沙箱环境)
在应用外部触发(Slack、定时任务、API)托管Agent
无人值守运行、需要在标签页关闭后继续运行或需要重试托管Agent
效果不依赖于查看者身份(共享写入、以系统身份发送)托管Agent
需要可审计或调试的运行历史托管Agent
两者可以组合使用:在页面中保留聊天界面,通过工具的
run
调用
agents.invoke
/
agents.start
委托繁重的步骤——请查看应用模式中的委托模式。反之亦然:托管Agent通常会搭配配套应用,用于管理其依赖的文件/记录、展示结果,并提供一键测试触发——请查看
$create-railcode-agent

Limitations

限制条件

When a request hits a row below, say so up front and offer the nearest supported shape. Do not quietly build an approximation that can't work.
Not possibleWhy, and the nearest supported path
Scrapers, or calls to arbitrary websites/APIsApps are same-origin (the SDK reaches only
/_api
); agent sandbox egress is allowlisted (PyPI/npm). Reach a specific API via an admin-configured service connector, or the caller's own personal connector — including any MCP server by URL
Custom backend code, or inbound endpoints (webhook receivers, public APIs)Apps are static; nothing listens. Poll the source through a connector (interactively or on an agent schedule) instead of receiving events
Public or customer-facing appsEvery viewer must be a signed-in org member — no anonymous access, no self-signup. Railcode apps are internal tools
Real-time push (websockets, live presence/collaboration)No push surface exists; UIs poll. LLM streaming is the only streaming response
Relational features over KV (joins, transactions, aggregations)KV queries filter/order/page only. Keep heavy data in a connected warehouse and read it via saved queries
Receiving email, or sending from a custom address
email.send()
is send-only with a platform-pinned sender and appended disclaimer
Multimodal LLM input, embeddings, or vector searchThe LLM gateway is text-in/text-out; there is no embeddings API. File understanding = a managed agent extracting in its sandbox
Long-running or event-driven automationAgent runs cap at 100 steps / 300 s; one cron per agent (null input); no data-change or inbound-webhook triggers (triggers are: app/API call, cron, Slack mention); agents can't invoke other agents
Heavy compute (model training, media transcoding)The sandbox is ephemeral per run with a 300 s ceiling; outputs must be published via
publish_artifact_to_app
Custom domains, native mobile apps, push notificationsApps are responsive web apps served at
<app>.<org>.<base-domain>
Bring-your-own API keys inside an appApps never hold secrets. Integrations exist only as admin-configured service connectors or the caller's personal connectors
当用户需求符合以下任意一条时,请直接说明并提供最接近的支持方案。切勿默默构建无法正常工作的近似版本。
无法实现原因及最接近的支持方案
爬虫或调用任意网站/API应用是同源的(SDK仅能访问
/_api
);Agent沙箱的出站请求是白名单制(仅允许PyPI/npm)。请通过管理员配置的服务连接器或调用者自己的个人连接器访问特定API——包括通过URL访问的任何MCP服务器
自定义后端代码或入站端点(Webhook接收器、公开API)应用是静态的;没有监听服务。请通过连接器轮询数据源(交互式或通过Agent计划任务),而非接收事件
公开或面向客户的应用所有查看者必须是已登录的组织成员——不支持匿名访问或自助注册。Railcode应用是内部工具
实时推送(websockets、在线状态/协作)无推送功能;UI通过轮询更新。LLM流式响应是唯一的流式输出
KV存储的关系型特性(关联、事务、聚合)KV查询仅支持过滤/排序/分页。请将大量数据存储在已连接的数据仓库中,通过已保存查询读取
接收邮件或从自定义地址发送邮件
email.send()
仅支持发送,发件人由平台固定并附加免责声明
多模态LLM输入、嵌入或向量搜索LLM网关仅支持文本输入/输出;无嵌入API。文件理解需由托管Agent在沙箱中提取内容
长时间运行或事件驱动的自动化Agent运行限制为100步/300秒;每个Agent仅支持一个定时任务(无输入);无数据变化或入站Webhook触发(触发方式:应用/API调用、定时任务、Slack提及);Agent无法调用其他Agent
重型计算(模型训练、媒体转码)沙箱每次运行是临时的,上限为300秒;输出必须通过
publish_artifact_to_app
发布
自定义域名、原生移动应用、推送通知应用是响应式Web应用,部署在
<app>.<org>.<base-domain>
在应用中使用自定义API密钥应用从不存储密钥。集成仅通过管理员配置的服务连接器或调用者的个人连接器实现

Visual Direction

视觉方向

Treat the starter/template app as functional scaffolding, not a style guide. Do not copy its visual style into new apps unless the active design system calls for it. An example copied from
railcode-examples
is different — it ships a coherent internal-tool look you can keep building on — but still reconcile it with the active design system rather than assuming the example already matches it.
If the user opted into the Railcode design system, fetch it first with
railcode design-system
(see Build Process step 2) and make the app follow it. When no design system is configured or reachable — or the user wants a different look — default to the Railcode design system: quiet internal-tool UI, neutral surfaces, compact controls, clear tables/lists, modest borders/radius, and restrained accent color.
Apps must be responsive. Verify the main workflows work cleanly on desktop and mobile widths, with no overlapping text, clipped controls, or unusable tables.
Give every app a favicon. These tools get pinned and left open in a row of tabs, so a default blank icon is a real cost. Draw a small SVG that says what the app is — a funnel for a pipeline, a board for a kanban, an envelope for an inbox — in the active design system's accent color, and link it from
index.html
:
html
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
Put the file in
public/favicon.svg
for the react template (Vite copies
public/
into the build output) or beside
index.html
for the no-build static template. Keep it readable at 16px: one shape, no fine detail, no lettering. Set a real
<title>
in the same file — it's the label next to that icon.
Keep data ownership explicit: use
db.user
/
files.user
for private data and
db.role(uuid)
/
files.role(uuid)
for role data; do not simulate scopes with key or path prefixes. Use query builders for large KV collections, bound parameters for SQL, and visible empty/error states for unconfigured integrations. Detailed patterns live in App patterns.
将初始/模板应用视为功能性脚手架,而非样式指南。除非当前设计系统要求,否则不要将其视觉风格复制到新应用中。从
railcode-examples
复制的示例则不同——它自带一套连贯的内部工具外观,可以在此基础上继续开发——但仍需与当前设计系统保持一致,不要假设示例已匹配设计系统。
如果用户选择使用Railcode设计系统,请先通过
railcode design-system
获取(请查看构建流程步骤2),并让应用遵循该设计系统。当未配置或无法访问设计系统时——或用户需要不同的外观——默认使用Railcode设计系统:简洁的内部工具UI、中性底色、紧凑控件、清晰的表格/列表、适度的边框/圆角和克制的强调色。
应用必须具备响应式特性。请验证主要工作流在桌面和移动宽度下都能正常运行,无文本重叠、控件裁剪或无法使用的表格。
为每个应用添加图标(favicon)。 这些工具会被固定并在标签页中持续打开,因此默认的空白图标会带来实际不便。请绘制一个小型SVG图标,表明应用的用途——例如管道应用用漏斗、看板应用用看板、收件箱应用用信封——使用当前设计系统的强调色,并在
index.html
中添加链接:
html
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
对于react模板,请将文件放入
public/favicon.svg
(Vite会将
public/
复制到构建输出中);对于无构建静态模板,请将文件放在
index.html
旁。请确保图标在16px尺寸下清晰可读:仅一个形状,无精细细节,无文字。请在同一文件中设置真实的
<title>
——它是图标旁的标签。
请明确数据所有权:使用
db.user
/
files.user
存储私有数据,使用
db.role(uuid)
/
files.role(uuid)
存储角色数据;不要使用键或路径前缀模拟作用域。对于大型KV集合,请使用查询构建器;对于SQL,请使用绑定参数;对于未配置的集成,请显示清晰的空状态/错误状态。详细模式请查看应用模式

Local Development

本地开发

Run
railcode dev
from the directory containing
railcode.json
and open the URL it prints. Identity, KV, and files are emulated locally; configured design, data, query, connector, LLM, personal-connector, and email calls are forwarded to the real instance when logged in. They can touch real data, incur spend, and cause side effects. Use
--reset
only when intentionally clearing this app's local KV/files. See CLI workflow.
Local dev storage is separate from the deployed app's:
railcode app kv
/
railcode app files
read and write the live app, never the local emulation.
在包含
railcode.json
的目录中执行
railcode dev
,然后打开它输出的URL。身份、KV和文件在本地模拟;已配置的设计、数据、查询、连接器、LLM、个人连接器和邮件调用在登录后会转发到真实实例。这些操作可能会触及真实数据、产生费用并导致副作用。仅当有意清除此应用的本地KV/文件时,才使用
--reset
参数。请查看CLI工作流
本地开发存储与已部署应用的存储是分离的:
railcode app kv
/
railcode app files
读取和写入在线应用,从不涉及本地模拟存储。

Validation

验证

Before handing off a new or changed app, run the app's normal build (the react template):
bash
cd <app>
npm run build
The no-build static template has no build step — just confirm the files load via
railcode dev
.
Seeding data to test with. An app with an empty store only ever shows empty states, so tables, sorting, pagination, and charts go unexercised. Once the app is deployed, seed a few realistic records with
railcode app kv set <collection> <key> '<json>'
(
--file
for anything long) and
railcode app files upload <path>
— matching the shape the app actually writes, which you can confirm with
railcode app kv get
after creating one record through the UI. Say what you seeded, and remove throwaway rows afterwards (
railcode app kv delete
, or
railcode app kv drop <collection> --yes
when the collection was yours alone). Ask first if the app already holds real data. This writes to the deployed app; under
railcode dev
, seed through the app's own UI instead — the CLI doesn't touch local dev storage.
If the user asked for browser testing (Build Process step 1), also exercise the running app before handing off. Start
railcode dev
, then open the printed local URL, usually
http://127.0.0.1:7331
, with whatever browser tooling you have — a browser-automation MCP, browser-use, or your harness's built-in browser. Load the app, walk the primary workflow end to end, and confirm it works at both desktop and mobile widths. Treat console errors, failed
/_api/*
calls, and broken layouts as failures to fix, not ship.
在交付新应用或修改后的应用前,请执行应用的常规构建(react模板):
bash
cd <app>
npm run build
无构建的静态模板无需构建步骤——只需通过
railcode dev
确认文件可正常加载。
植入测试数据。 存储为空的应用只会显示空状态,因此表格、排序、分页和图表无法得到充分测试。应用部署后,请使用
railcode app kv set <collection> <key> '<json>'
(内容较长时使用
--file
参数)和
railcode app files upload <path>
植入一些真实的测试记录——请匹配应用实际写入的数据格式,你可以通过UI创建一条记录后使用
railcode app kv get
确认格式。请说明你植入的数据,并在之后移除临时记录(
railcode app kv delete
,如果集合是你单独创建的,可使用
railcode app kv drop <collection> --yes
)。如果应用已包含真实数据,请先询问用户。此操作会写入已部署应用;在
railcode dev
模式下,请通过应用自身的UI植入测试数据——CLI不会触及本地开发存储。
如果用户在构建流程步骤1中要求浏览器测试,请在交付前测试运行中的应用。启动
railcode dev
,然后打开输出的本地URL(通常是
http://127.0.0.1:7331
),使用你拥有的任何浏览器工具——浏览器自动化MCP、浏览器使用工具或你的 harness 内置浏览器。加载应用,从头到尾走一遍主要工作流,确认它在桌面和移动宽度下都能正常运行。请将控制台错误、失败的
/_api/*
调用和布局损坏视为需要修复的问题,而非可交付的状态。

Deployment

部署

Deploy a finished app from its app directory:
bash
railcode deploy
Deploy reads
railcode.json
, builds when configured, uploads the resolved output, and prints the live URL. A new app defaults to organization-wide access; use
railcode deploy --private
for a private first deploy or set the intended policy explicitly afterward. Read Deployment for resolution, access modes, and verification.
If you did not create this app, you may not be its only deployer. Apps can carry editors — a co-deploy tier — so check your rights with
railcode apps show <app>
(
can edit
/
can manage
),
railcode pull
before deploying, and treat a deploy
409
as a colleague who published after your last sync rather than something to
--force
past. See Working In A Shared App.
To check what the live app actually stored — or to seed records and files into it — use
railcode app kv
/
railcode app files
(app owner or an org admin — not editors; see CLI workflow).
set
,
delete
,
drop
, and
upload
write real tenant data, so only run them when the user asked for it.
从应用目录部署已完成的应用:
bash
railcode deploy
部署命令会读取
railcode.json
,按配置构建,上传解析后的输出,并打印在线URL。新应用默认对整个组织开放访问;首次部署时可使用
railcode deploy --private
设置为私有,或在之后明确设置预期的访问策略。请查看部署了解解析、访问模式和验证方法。
如果你不是此应用的创建者,你可能不是唯一的部署者。 应用可以设置editors——共同部署层级——因此请使用
railcode apps show <app>
检查你的权限(
can edit
/
can manage
),在部署前执行
railcode pull
,并将部署时的
409
错误视为同事在你上次同步后已发布更新,而非使用
--force
强制覆盖。请查看在共享应用中工作
如需查看在线应用实际存储的数据——或向其中植入记录和文件——请使用
railcode app kv
/
railcode app files
(仅应用所有者或组织管理员有权限——不包括editors;请查看CLI工作流)。
set
delete
drop
upload
会写入真实的租户数据,因此仅当用户要求时才执行这些操作。